Skip to content

Commit

Permalink
feat: add file name option
Browse files Browse the repository at this point in the history
  • Loading branch information
anpigon committed Jun 15, 2022
1 parent 15900af commit 83626e7
Show file tree
Hide file tree
Showing 4 changed files with 183 additions and 1 deletion.
34 changes: 34 additions & 0 deletions src/settings/settings.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
import { App, PluginSettingTab, Setting } from 'obsidian';
import { replaceDateInString } from 'src/utils/utils';

import BookSearchPlugin from '../main';
import { FileNameFormatSuggest } from './suggesters/FileNameFormatSuggester';
import { FolderSuggest } from './suggesters/FolderSuggester';

const docUrl = 'https://github.com/anpigon/obsidian-book-search-plugin';
Expand All @@ -12,6 +14,7 @@ export enum DefaultFrontmatterKeyType {

export interface BookSearchPluginSettings {
folder: string;
fileNameFormat: string;
frontmatter: string;
content: string;
useDefaultFrontmatter: boolean;
Expand All @@ -20,6 +23,7 @@ export interface BookSearchPluginSettings {

export const DEFAULT_SETTINGS: BookSearchPluginSettings = {
folder: '',
fileNameFormat: '',
frontmatter: '',
content: '',
useDefaultFrontmatter: true,
Expand All @@ -39,6 +43,8 @@ export class BookSearchSettingTab extends PluginSettingTab {

containerEl.empty();

containerEl.classList.add('book-search-plugin__settings');

containerEl.createEl('h2', { text: 'General Settings' });

new Setting(containerEl)
Expand All @@ -58,6 +64,34 @@ export class BookSearchSettingTab extends PluginSettingTab {
});
});

const newFileNameEl = new Setting(containerEl);
const newFileNameHintEl = containerEl.createEl('div');
newFileNameHintEl.classList.add('setting-item-description')
newFileNameHintEl.classList.add('book-search-plugin__settings--new_file_name_hint')
const newFileNameHintDesc = document.createDocumentFragment();
const newFileNameHintDescCode = newFileNameHintDesc.createEl('code', { text: replaceDateInString(this.plugin.settings.fileNameFormat) || '{{title}} - {{author}}' })
newFileNameHintDesc.append(newFileNameHintDescCode);
newFileNameHintEl.append(newFileNameHintDesc);
newFileNameEl
.setClass('book-search-plugin__settings--new_file_name')
.setName('New file name')
.setDesc('Enter the file name format.')
.addSearch(cb => {
try {
new FileNameFormatSuggest(this.app, cb.inputEl);
} catch {
// eslint-disable
}
cb.setPlaceholder('Example: {{title}} - {{author}}')
.setValue(this.plugin.settings.fileNameFormat)
.onChange(newValue => {
this.plugin.settings.fileNameFormat = newValue;
this.plugin.saveSettings();

newFileNameHintDescCode.innerHTML = replaceDateInString(newValue) || '{{title}} - {{author}}';
});
});

containerEl.createEl('h2', { text: 'Frontmatter Settings' });

new Setting(containerEl)
Expand Down
83 changes: 83 additions & 0 deletions src/settings/suggesters/FileNameFormatSuggester.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
import type { App } from 'obsidian';
import { TextInputSuggest } from './suggest';

// == Format Syntax Suggestion == //
export const DATE_SYNTAX = '{{DATE}}';
export const DATE_FORMAT_SYNTAX = '{{DATE:}}';
export const DATE_SYNTAX_SUGGEST_REGEX = /{{D?A?T?E?}?}?$/i;
export const DATE_FORMAT_SYNTAX_SUGGEST_REGEX = /{{D?A?T?E?:?$|{{DATE:[^\n\r}]*}}$/i;

export const AUTHOR_SYNTAX = '{{author}}';
export const AUTHOR_SYNTAX_SUGGEST_REGEX = /{{a?u?t?h?o?r?}?}?$/i;

export const TITLE_SYNTAX = '{{title}}';
export const TITLE_SYNTAX_SUGGEST_REGEX = /{{t?i?t?l?e?}?}?$/i;

export class FileNameFormatSuggest extends TextInputSuggest<string> {
private lastInput = '';

constructor(public app: App, public inputEl: HTMLInputElement | HTMLTextAreaElement) {
super(app, inputEl);
}

getSuggestions(inputStr: string): string[] {
const cursorPosition: number = this.inputEl.selectionStart;
const lookbehind = 15;
const inputBeforeCursor = inputStr.substr(cursorPosition - lookbehind, lookbehind);
const suggestions: string[] = [];

this.processToken(inputBeforeCursor, (match: RegExpMatchArray, suggestion: string) => {
this.lastInput = match[0];
suggestions.push(suggestion);
});

return suggestions;
}

selectSuggestion(item: string): void {
const cursorPosition: number = this.inputEl.selectionStart;
const lastInputLength: number = this.lastInput.length;
const currentInputValue: string = this.inputEl.value;
let insertedEndPosition = 0;

const insert = (text: string, offset = 0) => {
return `${currentInputValue.substr(
0,
cursorPosition - lastInputLength + offset,
)}${text}${currentInputValue.substr(cursorPosition)}`;
};

this.processToken(item, (match, suggestion) => {
if (item.contains(suggestion)) {
this.inputEl.value = insert(item);
insertedEndPosition = cursorPosition - lastInputLength + item.length;

if (item === DATE_FORMAT_SYNTAX) {
insertedEndPosition -= 2;
}
}
});

this.inputEl.trigger('input');
this.close();
this.inputEl.setSelectionRange(insertedEndPosition, insertedEndPosition);
}

renderSuggestion(value: string, el: HTMLElement): void {
if (value) el.setText(value);
}

private processToken(input: string, callback: (match: RegExpMatchArray, suggestion: string) => void) {
const dateFormatMatch = DATE_FORMAT_SYNTAX_SUGGEST_REGEX.exec(input);
if (dateFormatMatch) callback(dateFormatMatch, DATE_FORMAT_SYNTAX);

const dateMatch = DATE_SYNTAX_SUGGEST_REGEX.exec(input);
if (dateMatch) callback(dateMatch, DATE_SYNTAX);

const authorMatch = AUTHOR_SYNTAX_SUGGEST_REGEX.exec(input);
if (authorMatch) callback(authorMatch, AUTHOR_SYNTAX);

const titleMatch = TITLE_SYNTAX_SUGGEST_REGEX.exec(input);
if (titleMatch) callback(titleMatch, TITLE_SYNTAX);
}
}
55 changes: 55 additions & 0 deletions src/utils/utils.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,11 @@
import { Book, FrontMatter } from 'src/models/book.model';
import { DefaultFrontmatterKeyType } from 'src/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(string: string) {
return string.replace(/[\\,#%&{}/*<>$":@.]*/g, '');
}
Expand Down Expand Up @@ -84,3 +89,53 @@ export function toStringFrontMatter(frontMatter: FrontMatter): string {
.map(([key, value]) => `${key}: ${value ?? ''}`)
.join('\n');
}

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: number;

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: offset }));
}

while (DATE_REGEX_FORMATTED.test(output)) {
const dateMatch = DATE_REGEX_FORMATTED.exec(output);
const format = dateMatch[1];
let offset: number;

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;
});
}
12 changes: 11 additions & 1 deletion styles.css
Original file line number Diff line number Diff line change
@@ -1 +1,11 @@
/* Sets all the text color to red! */
.book-search-plugin__settings .search-input-container {
width: 100%;
}

.book-search-plugin__settings--new_file_name {
padding-bottom: 0;
margin-bottom: 0;
}
.book-search-plugin__settings--new_file_name_hint {
margin-bottom: 20px;
}

0 comments on commit 83626e7

Please sign in to comment.