mirror of
https://github.com/cmorooney/obsidian-game-search-plugin.git
synced 2026-07-22 07:50:25 +00:00
157 lines
4.5 KiB
TypeScript
157 lines
4.5 KiB
TypeScript
import { Game, FrontMatter } from '@models/game.model';
|
|
import { DefaultFrontmatterKeyType } from '@settings/settings';
|
|
|
|
// == Format Syntax == //
|
|
export const NUMBER_REGEX = /^-?[0-9]*$/;
|
|
export const DATE_REGEX = /{{DATE(\+-?[0-9]+)?}}/;
|
|
export const DATE_REGEX_FORMATTED = /{{DATE:([^}\n\r+]*)(\+-?[0-9]+)?}}/;
|
|
|
|
export function replaceIllegalFileNameCharactersInString(text: string) {
|
|
return text.replace(/[\\,#%&{}/*<>$":@.]/g, '').replace(/\s+/g, ' ');
|
|
}
|
|
|
|
export function isISBN(str: string) {
|
|
return /^(97(8|9))?\d{9}(\d|X)$/.test(str);
|
|
}
|
|
|
|
export function makeFileName(game: Game, fileNameFormat?: string) {
|
|
let result;
|
|
if (fileNameFormat) {
|
|
result = replaceVariableSyntax(game, replaceDateInString(fileNameFormat));
|
|
} else {
|
|
result = !game.released ? game.name : `${game.name} - ${game.released}`;
|
|
}
|
|
return replaceIllegalFileNameCharactersInString(result) + '.md';
|
|
}
|
|
|
|
export function changeSnakeCase(game: Game) {
|
|
return Object.entries(game).reduce((acc, [key, value]) => {
|
|
acc[camelToSnakeCase(key)] = value;
|
|
return acc;
|
|
}, {});
|
|
}
|
|
|
|
export function applyDefaultFrontMatter(
|
|
game: Game,
|
|
frontmatter: FrontMatter | string,
|
|
keyType: DefaultFrontmatterKeyType = DefaultFrontmatterKeyType.snakeCase,
|
|
) {
|
|
const frontMater = keyType === DefaultFrontmatterKeyType.camelCase ? game : changeSnakeCase(game);
|
|
|
|
const extraFrontMatter = typeof frontmatter === 'string' ? parseFrontMatter(frontmatter) : frontmatter;
|
|
for (const key in extraFrontMatter) {
|
|
const value = extraFrontMatter[key]?.toString().trim() ?? '';
|
|
if (frontMater[key] && frontMater[key] !== value) {
|
|
frontMater[key] = `${frontMater[key]}, ${value}`;
|
|
} else {
|
|
frontMater[key] = value;
|
|
}
|
|
}
|
|
|
|
return frontMater as object;
|
|
}
|
|
|
|
export function replaceVariableSyntax(game: Game, text: string): string {
|
|
if (!text?.trim()) {
|
|
return '';
|
|
}
|
|
|
|
const entries = Object.entries(game);
|
|
|
|
return entries
|
|
.reduce((result, [key, val = '']) => {
|
|
return result.replace(new RegExp(`{{${key}}}`, 'ig'), val);
|
|
}, text)
|
|
.replace(/{{\w+}}/gi, '')
|
|
.trim();
|
|
}
|
|
|
|
export function camelToSnakeCase(str) {
|
|
return str.replace(/[A-Z]/g, letter => `_${letter?.toLowerCase()}`);
|
|
}
|
|
|
|
export function parseFrontMatter(frontMatterString: string) {
|
|
if (!frontMatterString) return {};
|
|
return frontMatterString
|
|
.split('\n')
|
|
.map(item => {
|
|
const index = item.indexOf(':');
|
|
if (index === -1) return [item.trim(), ''];
|
|
|
|
const key = item.slice(0, index)?.trim();
|
|
const value = item.slice(index + 1)?.trim();
|
|
return [key, value];
|
|
})
|
|
.reduce((acc, [key, value]) => {
|
|
if (key) {
|
|
acc[key] = value?.trim() ?? '';
|
|
}
|
|
return acc;
|
|
}, {});
|
|
}
|
|
|
|
export function toStringFrontMatter(frontMatter: object): string {
|
|
return Object.entries(frontMatter)
|
|
.map(([key, value]) => {
|
|
const newValue = value?.toString().trim() ?? '';
|
|
if (/\r|\n/.test(newValue)) {
|
|
return '';
|
|
}
|
|
if (/:\s/.test(newValue)) {
|
|
return `${key}: "${newValue.replace(/"/g, '"')}"\n`;
|
|
}
|
|
return `${key}: ${newValue}\n`;
|
|
})
|
|
.join('')
|
|
.trim();
|
|
}
|
|
|
|
export function getDate(input?: { format?: string; offset?: number }) {
|
|
let duration;
|
|
|
|
if (input?.offset !== null && input?.offset !== undefined && typeof input.offset === 'number') {
|
|
duration = window.moment.duration(input.offset, 'days');
|
|
}
|
|
|
|
return input?.format
|
|
? window.moment().add(duration).format(input?.format)
|
|
: window.moment().add(duration).format('YYYY-MM-DD');
|
|
}
|
|
|
|
export function replaceDateInString(input: string) {
|
|
let output: string = input;
|
|
|
|
while (DATE_REGEX.test(output)) {
|
|
const dateMatch = DATE_REGEX.exec(output);
|
|
let offset = 0;
|
|
|
|
if (dateMatch?.[1]) {
|
|
const offsetString = dateMatch[1].replace('+', '').trim();
|
|
const offsetIsInt = NUMBER_REGEX.test(offsetString);
|
|
if (offsetIsInt) offset = parseInt(offsetString);
|
|
}
|
|
output = replacer(output, DATE_REGEX, getDate({ offset }));
|
|
}
|
|
|
|
while (DATE_REGEX_FORMATTED.test(output)) {
|
|
const dateMatch = DATE_REGEX_FORMATTED.exec(output);
|
|
const format = dateMatch?.[1];
|
|
let offset = 0;
|
|
|
|
if (dateMatch?.[2]) {
|
|
const offsetString = dateMatch[2].replace('+', '').trim();
|
|
const offsetIsInt = NUMBER_REGEX.test(offsetString);
|
|
if (offsetIsInt) offset = parseInt(offsetString);
|
|
}
|
|
|
|
output = replacer(output, DATE_REGEX_FORMATTED, getDate({ format, offset }));
|
|
}
|
|
|
|
return output;
|
|
}
|
|
|
|
function replacer(str: string, reg: RegExp, replaceValue) {
|
|
return str.replace(reg, function () {
|
|
return replaceValue;
|
|
});
|
|
}
|