From 520269135d07f5447041360f33099fdd8f1273e7 Mon Sep 17 00:00:00 2001 From: Peter Kaufman Date: Sun, 30 Jun 2024 17:11:55 -0400 Subject: [PATCH 01/10] added an initial base for how to work with custom file selection from users for auto correct --- src/lang/locale/en.ts | 4 ++ src/option.ts | 39 +++++++++++ src/rules/auto-correct-common-misspellings.ts | 9 ++- src/rules/rule-builder.ts | 8 ++- .../auto-correct-files-picker-option.ts | 67 +++++++++++++++++++ .../tab-components/rule-tab.ts | 6 ++ src/ui/suggesters/folder-suggester.ts | 2 +- src/ui/suggesters/md-file-suggester.ts | 44 ++++++++++++ 8 files changed, 176 insertions(+), 3 deletions(-) create mode 100644 src/ui/linter-components/auto-correct-files-picker-option.ts create mode 100644 src/ui/suggesters/md-file-suggester.ts diff --git a/src/lang/locale/en.ts b/src/lang/locale/en.ts index eec64219..4619b789 100644 --- a/src/lang/locale/en.ts +++ b/src/lang/locale/en.ts @@ -243,6 +243,10 @@ export default { 'name': 'Ignore Words', 'description': 'A comma separated list of lowercased words to ignore when auto-correcting', }, + 'extra-auto-correct-files': { + 'name': 'Extra Auto-Correct Source Files', + 'description': 'These are files that have a markdown table in them that have the initial word and the word to correct it to (these are case insensitive corrections). **Note: the tables used should have the starting and ending `|` indicators present for each line.**', + }, }, // add-blank-line-after-yaml.ts 'add-blank-line-after-yaml': { diff --git a/src/option.ts b/src/option.ts index c5e01d3d..7fb1557a 100644 --- a/src/option.ts +++ b/src/option.ts @@ -3,6 +3,7 @@ import {getTextInLanguage, LanguageStringKey} from './lang/helpers'; import LinterPlugin from './main'; import {parseTextToHTMLWithoutOuterParagraph} from './ui/helpers'; import {LinterSettings} from './settings-data'; +import {AutoCorrectFilesPickerOption} from './ui/linter-components/auto-correct-files-picker-option'; export type SearchOptionInfo = {name: string, description: string, options?: DropdownRecord[]} @@ -171,3 +172,41 @@ export class DropdownOption extends Option { this.parseNameAndDescriptionAndRemoveSettingBorder(setting, plugin); } } + + +export class MdFilePickerOption extends Option { + constructor(configKey: string, nameKey: LanguageStringKey, descriptionKey: LanguageStringKey, ruleAlias?: string | null) { + super(configKey, nameKey, descriptionKey, [], ruleAlias); + } + + public display(containerEl: HTMLElement, settings: LinterSettings, plugin: LinterPlugin): void { + // const folderIgnoreEl = this.contentEl.createDiv(); + console.log(this.configKey); + console.log(settings.ruleConfigs[this.ruleAlias]); + console.log(settings.ruleConfigs[this.ruleAlias][this.configKey]); + new AutoCorrectFilesPickerOption(containerEl, plugin.settingsTab.component, settings.ruleConfigs[this.ruleAlias][this.configKey], plugin.app, () => { + plugin.saveSettings(); + }, this.nameKey, this.descriptionKey); + + // this.addSettingSearchInfo(folderIgnoreEl, folderIgnore.name, folderIgnore.description.replaceAll('\n', ' ')); + + // const setting = new Setting(containerEl) + // .addDropdown((dropdown) => { + // // First, add all the available options + // for (const option of this.options) { + // dropdown.addOption(option.value.replace('enums.', ''), option.getDisplayValue()); + // } + + // // Set currently selected value from existing settings + // dropdown.setValue(settings.ruleConfigs[this.ruleAlias][this.configKey]); + + // dropdown.onChange((value) => { + // this.setOption(value, settings); + // plugin.settings = settings; + // plugin.saveSettings(); + // }); + // }); + + // this.parseNameAndDescriptionAndRemoveSettingBorder(setting, plugin); + } +} diff --git a/src/rules/auto-correct-common-misspellings.ts b/src/rules/auto-correct-common-misspellings.ts index 6602e1d4..cd802b9c 100644 --- a/src/rules/auto-correct-common-misspellings.ts +++ b/src/rules/auto-correct-common-misspellings.ts @@ -1,12 +1,13 @@ import {IgnoreTypes} from '../utils/ignore-types'; import {Options, RuleType} from '../rules'; -import RuleBuilder, {ExampleBuilder, OptionBuilderBase, TextAreaOptionBuilder} from './rule-builder'; +import RuleBuilder, {ExampleBuilder, MdFilePickerOptionBuilder, OptionBuilderBase, TextAreaOptionBuilder} from './rule-builder'; import dedent from 'ts-dedent'; import {misspellingToCorrection} from '../utils/auto-correct-misspellings'; import {wordRegex, wordSplitterRegex} from '../utils/regex'; class AutoCorrectCommonMisspellingsOptions implements Options { ignoreWords?: string[] = []; + extraAutoCorrectFiles?: string[] = []; } @RuleBuilder.register @@ -115,6 +116,12 @@ export default class AutoCorrectCommonMisspellings extends RuleBuilder extends OptionB return new MomentFormatOption(this.configKey, this.nameKey, this.descriptionKey, this.defaultValue); } } + +export class MdFilePickerOptionBuilder extends OptionBuilder { + protected buildOption(): Option { + return new MdFilePickerOption(this.configKey, this.nameKey, this.descriptionKey); + } +} diff --git a/src/ui/linter-components/auto-correct-files-picker-option.ts b/src/ui/linter-components/auto-correct-files-picker-option.ts new file mode 100644 index 00000000..869eca9c --- /dev/null +++ b/src/ui/linter-components/auto-correct-files-picker-option.ts @@ -0,0 +1,67 @@ +import {Setting, Component, App} from 'obsidian'; +import {LanguageStringKey, getTextInLanguage} from 'src/lang/helpers'; +import {AddCustomRow} from '../components/add-custom-row'; +import MdFileSuggester from '../suggesters/md-file-suggester'; + +export class AutoCorrectFilesPickerOption extends AddCustomRow { + constructor(containerEl: HTMLElement, parentComponent: Component, public filesPicked: string[], private app: App, saveSettings: () => void, name: LanguageStringKey, description: LanguageStringKey) { + super( + containerEl, + parentComponent, + getTextInLanguage(name), + getTextInLanguage(description), + null, + 'Add another custom file', + saveSettings, + ()=>{ + const newPickedFile = ''; + this.filesPicked.push(newPickedFile); + this.saveSettings(); + this.addPickedFile(newPickedFile, this.filesPicked.length - 1, true); + }); + this.display(); + this.inputElDiv.addClass('linter-folder-ignore-container'); + } + + protected showInputEls(): void { + this.filesPicked.forEach((pickedFile, index) => { + this.addPickedFile(pickedFile, index); + }); + } + + private addPickedFile(pickedFile: string, index: number, focusOnCommand: boolean = false) { + const setting = new Setting(this.inputElDiv) + .addSearch((cb) => { + new MdFileSuggester(this.app, cb.inputEl, this.filesPicked); + cb.setPlaceholder(getTextInLanguage('tabs.general.folders-to-ignore.folder-search-placeholder-text')) + .setValue(pickedFile) + .onChange((newFolderToIgnore) => { + // TODO: add the logic for when a file exists and has been selected that we parse that file's contents into the extra words list + const folderToIgnore = newFolderToIgnore; + + if (folderToIgnore === '' || folderToIgnore === cb.inputEl.getAttribute('fileName')) { + this.filesPicked[index] = folderToIgnore; + this.saveSettings(); + } + }); + + cb.inputEl.setAttr('tabIndex', index); + cb.inputEl.addClass('linter-folder-ignore'); + + if (focusOnCommand) { + cb.inputEl.focus(); + } + }) + .addExtraButton((cb) => { + cb.setIcon('cross') + .setTooltip(getTextInLanguage('tabs.general.folders-to-ignore.delete-tooltip')) + .onClick(() => { + this.filesPicked.splice(index, 1); + this.saveSettings(); + this.resetInputEls(); + }); + }); + + setting.settingEl.addClass('linter-no-border'); + } +} diff --git a/src/ui/linter-components/tab-components/rule-tab.ts b/src/ui/linter-components/tab-components/rule-tab.ts index 76fe4ff2..8c85daac 100644 --- a/src/ui/linter-components/tab-components/rule-tab.ts +++ b/src/ui/linter-components/tab-components/rule-tab.ts @@ -23,6 +23,12 @@ export class RuleTab extends Tab { optionInfo.push(option.getSearchInfo()); } + // // add file picker for custom inputs to auto-correct-common-misspellings + // if (rule.alias === 'auto-correct-common-misspellings') { + + // } + + this.addSettingSearchInfo(ruleDiv, rule.getName().toLowerCase(), rule.getDescription().toLowerCase(), optionInfo, ruleDiv.id); } } diff --git a/src/ui/suggesters/folder-suggester.ts b/src/ui/suggesters/folder-suggester.ts index 47585cd7..6fb64864 100644 --- a/src/ui/suggesters/folder-suggester.ts +++ b/src/ui/suggesters/folder-suggester.ts @@ -17,7 +17,7 @@ export default class FolderSuggester extends TextInputSuggest { } const nonSelectedFolders = all_folders.filter((el: string) => { - return !this.valuesToExclude.includes(el) || el === this.inputEl.getAttribute('folderExists'); + return !this.valuesToExclude.includes(el) || el === this.inputEl.getAttribute('folderName'); }); const folders: string[] = []; diff --git a/src/ui/suggesters/md-file-suggester.ts b/src/ui/suggesters/md-file-suggester.ts new file mode 100644 index 00000000..26da7a3d --- /dev/null +++ b/src/ui/suggesters/md-file-suggester.ts @@ -0,0 +1,44 @@ +import {TextInputSuggest} from './suggest'; +import {App, TFile} from 'obsidian'; + +export default class MdFileSuggester extends TextInputSuggest { + constructor( + public app: App, + public inputEl: HTMLInputElement, + public valuesToExclude: string[] = [], + ) { + super(app, inputEl); + } + + getSuggestions(input_str: string): string[] { + const all_md_files = this.app.vault.getAllLoadedFiles().filter((f) => f instanceof TFile && f.path.endsWith('.md')).map((f) => f.path); + if (!all_md_files) { + return []; + } + + const nonSelectedMdFiles = all_md_files.filter((el: string) => { + return !this.valuesToExclude.includes(el) || el === this.inputEl.getAttribute('fileName'); + }); + + const files: string[] = []; + const lower_input_str = input_str.toLowerCase(); + nonSelectedMdFiles.forEach((folderPath: string) => { + if (folderPath.toLowerCase().contains(lower_input_str)) { + files.push(folderPath); + } + }); + + return files; + } + + renderSuggestion(filePath: string, el: HTMLElement): void { + el.setText(filePath); + } + + selectSuggestion(filePath: string): void { + this.inputEl.setAttribute('fileName', filePath); + this.inputEl.value = filePath; + this.inputEl.trigger('input'); + this.close(); + } +} From 3c476e8b0732edb672b36551c4eedaaa11b7e39d Mon Sep 17 00:00:00 2001 From: Peter Kaufman Date: Mon, 5 Aug 2024 21:35:59 -0400 Subject: [PATCH 02/10] got it theoretically working, but so far it is not saving properly --- src/rules/auto-correct-common-misspellings.ts | 27 +++++++--- .../auto-correct-files-picker-option.ts | 51 +++++++++++++++---- src/ui/suggesters/md-file-suggester.ts | 3 +- src/utils/strings.ts | 30 +++++++++++ 4 files changed, 93 insertions(+), 18 deletions(-) diff --git a/src/rules/auto-correct-common-misspellings.ts b/src/rules/auto-correct-common-misspellings.ts index cd802b9c..df7359de 100644 --- a/src/rules/auto-correct-common-misspellings.ts +++ b/src/rules/auto-correct-common-misspellings.ts @@ -4,10 +4,11 @@ import RuleBuilder, {ExampleBuilder, MdFilePickerOptionBuilder, OptionBuilderBas import dedent from 'ts-dedent'; import {misspellingToCorrection} from '../utils/auto-correct-misspellings'; import {wordRegex, wordSplitterRegex} from '../utils/regex'; +import {CustomAutoCorrectContent} from '../ui/linter-components/auto-correct-files-picker-option'; class AutoCorrectCommonMisspellingsOptions implements Options { ignoreWords?: string[] = []; - extraAutoCorrectFiles?: string[] = []; + extraAutoCorrectFiles?: CustomAutoCorrectContent[] = []; } @RuleBuilder.register @@ -28,16 +29,30 @@ export default class AutoCorrectCommonMisspellings extends RuleBuilder[] { return [ diff --git a/src/ui/linter-components/auto-correct-files-picker-option.ts b/src/ui/linter-components/auto-correct-files-picker-option.ts index 869eca9c..2c96e282 100644 --- a/src/ui/linter-components/auto-correct-files-picker-option.ts +++ b/src/ui/linter-components/auto-correct-files-picker-option.ts @@ -1,10 +1,15 @@ -import {Setting, Component, App} from 'obsidian'; +import {Setting, Component, App, TFile, normalizePath} from 'obsidian'; import {LanguageStringKey, getTextInLanguage} from 'src/lang/helpers'; import {AddCustomRow} from '../components/add-custom-row'; import MdFileSuggester from '../suggesters/md-file-suggester'; +import {parseCustomReplacements, stripCr} from '../../utils/strings'; + +export type CustomAutoCorrectContent = {filePath: string, customReplacements: Map}; export class AutoCorrectFilesPickerOption extends AddCustomRow { - constructor(containerEl: HTMLElement, parentComponent: Component, public filesPicked: string[], private app: App, saveSettings: () => void, name: LanguageStringKey, description: LanguageStringKey) { + private selectedFiles: string[] = []; + + constructor(containerEl: HTMLElement, parentComponent: Component, public filesPicked: CustomAutoCorrectContent[] = [], private app: App, saveSettings: () => void, name: LanguageStringKey, description: LanguageStringKey) { super( containerEl, parentComponent, @@ -14,8 +19,14 @@ export class AutoCorrectFilesPickerOption extends AddCustomRow { 'Add another custom file', saveSettings, ()=>{ - const newPickedFile = ''; + this.selectedFiles = []; + for (const filePicked of this.filesPicked) { + this.selectedFiles.push(filePicked.filePath); + } + + const newPickedFile: CustomAutoCorrectContent = {filePath: '', customReplacements: null}; this.filesPicked.push(newPickedFile); + this.selectedFiles.push(''); this.saveSettings(); this.addPickedFile(newPickedFile, this.filesPicked.length - 1, true); }); @@ -29,18 +40,27 @@ export class AutoCorrectFilesPickerOption extends AddCustomRow { }); } - private addPickedFile(pickedFile: string, index: number, focusOnCommand: boolean = false) { + private addPickedFile(pickedFile: CustomAutoCorrectContent, index: number, focusOnCommand: boolean = false) { const setting = new Setting(this.inputElDiv) .addSearch((cb) => { - new MdFileSuggester(this.app, cb.inputEl, this.filesPicked); + new MdFileSuggester(this.app, cb.inputEl, this.selectedFiles); cb.setPlaceholder(getTextInLanguage('tabs.general.folders-to-ignore.folder-search-placeholder-text')) - .setValue(pickedFile) - .onChange((newFolderToIgnore) => { - // TODO: add the logic for when a file exists and has been selected that we parse that file's contents into the extra words list - const folderToIgnore = newFolderToIgnore; + .setValue(pickedFile.filePath) + .onChange(async (newPickedFile) => { + const customReplacementFile = newPickedFile; - if (folderToIgnore === '' || folderToIgnore === cb.inputEl.getAttribute('fileName')) { - this.filesPicked[index] = folderToIgnore; + if (customReplacementFile === '' || customReplacementFile === cb.inputEl.getAttribute('fileName')) { + console.log('getting file from path...'); + const file = this.getFileFromPath(customReplacementFile); + pickedFile.filePath = customReplacementFile; + if (file) { + pickedFile.customReplacements = parseCustomReplacements(stripCr(await this.app.vault.read(file))); + } else { + pickedFile.customReplacements = null; + } + + console.log(pickedFile); + this.filesPicked[index] = pickedFile; this.saveSettings(); } }); @@ -64,4 +84,13 @@ export class AutoCorrectFilesPickerOption extends AddCustomRow { setting.settingEl.addClass('linter-no-border'); } + + private getFileFromPath(filePath: string): TFile { + const file = this.app.vault.getAbstractFileByPath(normalizePath(filePath)); + if (file instanceof TFile) { + return file; + } + + return null; + } } diff --git a/src/ui/suggesters/md-file-suggester.ts b/src/ui/suggesters/md-file-suggester.ts index 26da7a3d..8bec0b63 100644 --- a/src/ui/suggesters/md-file-suggester.ts +++ b/src/ui/suggesters/md-file-suggester.ts @@ -1,3 +1,4 @@ +import {CustomAutoCorrectContent} from '../linter-components/auto-correct-files-picker-option'; import {TextInputSuggest} from './suggest'; import {App, TFile} from 'obsidian'; @@ -5,7 +6,7 @@ export default class MdFileSuggester extends TextInputSuggest { constructor( public app: App, public inputEl: HTMLInputElement, - public valuesToExclude: string[] = [], + public valuesToExclude: CustomAutoCorrectContent[] = [], ) { super(app, inputEl); } diff --git a/src/utils/strings.ts b/src/utils/strings.ts index e6cc13bd..8ce6fc4b 100644 --- a/src/utils/strings.ts +++ b/src/utils/strings.ts @@ -1,4 +1,6 @@ import {calloutRegex, codeBlockBlockquoteRegex} from './regex'; +import {logWarn} from './logger'; +import {getAllTablesInText} from './mdast'; /** * Inserts a string at the given position in a string. * @param {string} str - The string to insert into @@ -505,3 +507,31 @@ function getIndexOfEndOfLastNonEmptyLine(text: string, currentEndOfBlockquote: n return currentEndOfBlockquote; } + +export function parseCustomReplacements(text: string): Map { + const tableInfo = getAllTablesInText(text); + const customReplacements = new Map(); + + let tableContent = ''; + let tableRows = [] as string[]; + let rowParts = [] as string[]; + for (const table of tableInfo) { + tableContent = text.substring(table.startIndex, table.endIndex); + tableRows = tableContent.split('\n'); + tableRows.splice(0, 2); // skip header and divider rows + + for (const row of tableRows) { + rowParts = row.split('|'); + + if (rowParts.length !== 4) { + // TODO: move this to en.ts + logWarn(`"${row}" is not a valid row with custom replacements. It must have only 2 columns.`); + continue; + } + + customReplacements.set(rowParts[1].trim().toLowerCase(), rowParts[2].trim()); + } + } + + return customReplacements; +} From 0e7595e508cf590ff447d915dc10df831f5a37b5 Mon Sep 17 00:00:00 2001 From: Peter Kaufman Date: Mon, 5 Aug 2024 21:52:58 -0400 Subject: [PATCH 03/10] added some logic to allow the settings data to be retained and used by the rule itself. So far it looks to be working --- src/main.ts | 24 +++++++++++++++++-- src/option.ts | 2 ++ .../auto-correct-files-picker-option.ts | 2 +- src/ui/suggesters/md-file-suggester.ts | 3 +-- 4 files changed, 26 insertions(+), 5 deletions(-) diff --git a/src/main.ts b/src/main.ts index 677560bd..5310eb74 100644 --- a/src/main.ts +++ b/src/main.ts @@ -1,8 +1,8 @@ -import {App, Editor, EventRef, MarkdownView, Menu, Notice, Plugin, TAbstractFile, TFile, TFolder, addIcon, htmlToMarkdown, EditorSelection, EditorChange, MarkdownViewModeType, getFrontMatterInfo, FileView} from 'obsidian'; +import {App, Editor, EventRef, MarkdownView, Menu, Notice, Plugin, TAbstractFile, TFile, TFolder, addIcon, htmlToMarkdown, EditorSelection, EditorChange, MarkdownViewModeType, getFrontMatterInfo, FileView, normalizePath} from 'obsidian'; import {Options, RuleType, ruleTypeToRules, rules} from './rules'; import DiffMatchPatch from 'diff-match-patch'; import dedent from 'ts-dedent'; -import {stripCr} from './utils/strings'; +import {parseCustomReplacements, stripCr} from './utils/strings'; import {logInfo, logError, logDebug, setLogLevel, logWarn, setCollectLogs, clearLogs, convertNumberToLogLevel} from './utils/logger'; import {moment} from 'obsidian'; import './rules-registry'; @@ -17,6 +17,7 @@ import {RuleAliasSuggest} from './cm6/rule-alias-suggester'; import {DEFAULT_SETTINGS, LinterSettings} from './settings-data'; import AsyncLock from 'async-lock'; import {warn} from 'loglevel'; +import {CustomAutoCorrectContent} from './ui/linter-components/auto-correct-files-picker-option'; // https://github.com/liamcain/obsidian-calendar-ui/blob/03ceecbf6d88ef260dadf223ee5e483d98d24ffc/src/localization.ts#L20-L43 const langToMomentLocale = { @@ -138,6 +139,16 @@ export default class LinterPlugin extends Plugin { } } + // load the custom replacements since they are not stored in the data.json when the settings data is saved + for (const replacementFileInfo of this.settings.ruleConfigs['auto-correct-common-misspellings']['extra-auto-correct-files'] as CustomAutoCorrectContent[]) { + if (replacementFileInfo.filePath != '') { + const file = this.getFileFromPath(replacementFileInfo.filePath); + if (file) { + replacementFileInfo.customReplacements = parseCustomReplacements(stripCr(await this.app.vault.cachedRead(file))); + } + } + } + this.updatePasteOverrideStatus(); this.updateHasCustomCommandStatus(); } @@ -869,4 +880,13 @@ export default class LinterPlugin extends Plugin { const lines = doc.split('\n'); return {line: lines.length - 1, ch: lines[lines.length - 1].length}; } + + private getFileFromPath(filePath: string): TFile { + const file = this.app.vault.getAbstractFileByPath(normalizePath(filePath)); + if (file instanceof TFile) { + return file; + } + + return null; + } } diff --git a/src/option.ts b/src/option.ts index 7fb1557a..dcdadf0b 100644 --- a/src/option.ts +++ b/src/option.ts @@ -184,6 +184,8 @@ export class MdFilePickerOption extends Option { console.log(this.configKey); console.log(settings.ruleConfigs[this.ruleAlias]); console.log(settings.ruleConfigs[this.ruleAlias][this.configKey]); + settings.ruleConfigs[this.ruleAlias][this.configKey] = settings.ruleConfigs[this.ruleAlias][this.configKey] ?? []; + new AutoCorrectFilesPickerOption(containerEl, plugin.settingsTab.component, settings.ruleConfigs[this.ruleAlias][this.configKey], plugin.app, () => { plugin.saveSettings(); }, this.nameKey, this.descriptionKey); diff --git a/src/ui/linter-components/auto-correct-files-picker-option.ts b/src/ui/linter-components/auto-correct-files-picker-option.ts index 2c96e282..0558afd7 100644 --- a/src/ui/linter-components/auto-correct-files-picker-option.ts +++ b/src/ui/linter-components/auto-correct-files-picker-option.ts @@ -9,7 +9,7 @@ export type CustomAutoCorrectContent = {filePath: string, customReplacements: Ma export class AutoCorrectFilesPickerOption extends AddCustomRow { private selectedFiles: string[] = []; - constructor(containerEl: HTMLElement, parentComponent: Component, public filesPicked: CustomAutoCorrectContent[] = [], private app: App, saveSettings: () => void, name: LanguageStringKey, description: LanguageStringKey) { + constructor(containerEl: HTMLElement, parentComponent: Component, public filesPicked: CustomAutoCorrectContent[], private app: App, saveSettings: () => void, name: LanguageStringKey, description: LanguageStringKey) { super( containerEl, parentComponent, diff --git a/src/ui/suggesters/md-file-suggester.ts b/src/ui/suggesters/md-file-suggester.ts index 8bec0b63..26da7a3d 100644 --- a/src/ui/suggesters/md-file-suggester.ts +++ b/src/ui/suggesters/md-file-suggester.ts @@ -1,4 +1,3 @@ -import {CustomAutoCorrectContent} from '../linter-components/auto-correct-files-picker-option'; import {TextInputSuggest} from './suggest'; import {App, TFile} from 'obsidian'; @@ -6,7 +5,7 @@ export default class MdFileSuggester extends TextInputSuggest { constructor( public app: App, public inputEl: HTMLInputElement, - public valuesToExclude: CustomAutoCorrectContent[] = [], + public valuesToExclude: string[] = [], ) { super(app, inputEl); } From be9909f0d981e94ddef39124720170517be0e479 Mon Sep 17 00:00:00 2001 From: Peter Kaufman Date: Fri, 9 Aug 2024 21:37:34 -0400 Subject: [PATCH 04/10] cleaned up the ghost code, moved the new text to the localization files, and added the modal to shwo the user what contents exist in the parsed file --- src/lang/locale/en.ts | 15 +++++++++ src/option.ts | 22 ------------- .../auto-correct-files-picker-option.ts | 16 ++++++--- .../tab-components/rule-tab.ts | 6 ---- src/ui/modals/lint-confirmation-modal.ts | 2 +- src/ui/modals/parse-results-modal.ts | 33 +++++++++++++++++++ src/utils/strings.ts | 4 +-- 7 files changed, 62 insertions(+), 36 deletions(-) create mode 100644 src/ui/modals/parse-results-modal.ts diff --git a/src/lang/locale/en.ts b/src/lang/locale/en.ts index 4619b789..0381b1b2 100644 --- a/src/lang/locale/en.ts +++ b/src/lang/locale/en.ts @@ -104,9 +104,17 @@ export default { 'warning-text': 'Warning', 'file-backup-text': 'Make sure you have backed up your files.', 'custom-command-warning': 'Linting multiple files with custom commands enabled is a slow process that requires the ability to open panes in the side panel. It is noticeably slower than running without custom commands enabled. Please proceed with caution.', + 'cancel-button-text': 'Cancel', 'copy-aria-label': 'Copy', + // parse-results-modal.ts + 'parse-results-heading-text': 'Custom Parse Values', + 'file-parse-description-text': 'The following is the list of custom replacements found in {FILE}.', + 'find-header-text': 'Word to Find', + 'replace-header-text': 'Replacement Word', + 'close-button-text': 'Close', + 'tabs': { 'names': { // tab.ts @@ -231,6 +239,13 @@ export default { 'move-down-tooltip': 'Move down', 'delete-tooltip': 'Delete', }, + 'custom-auto-correct': { + 'delete-tooltip': 'Delete', + 'show-parsed-contents-tooltip': 'View parsed replacements', + 'custom-row-parse-warning': '"{ROW}" is not a valid row with custom replacements. It must have only 2 columns.', + 'file-search-placeholder-text': 'File name', + 'add-input-button-text': 'Add another custom file', + }, }, // rules diff --git a/src/option.ts b/src/option.ts index dcdadf0b..c04ad5f3 100644 --- a/src/option.ts +++ b/src/option.ts @@ -180,7 +180,6 @@ export class MdFilePickerOption extends Option { } public display(containerEl: HTMLElement, settings: LinterSettings, plugin: LinterPlugin): void { - // const folderIgnoreEl = this.contentEl.createDiv(); console.log(this.configKey); console.log(settings.ruleConfigs[this.ruleAlias]); console.log(settings.ruleConfigs[this.ruleAlias][this.configKey]); @@ -189,26 +188,5 @@ export class MdFilePickerOption extends Option { new AutoCorrectFilesPickerOption(containerEl, plugin.settingsTab.component, settings.ruleConfigs[this.ruleAlias][this.configKey], plugin.app, () => { plugin.saveSettings(); }, this.nameKey, this.descriptionKey); - - // this.addSettingSearchInfo(folderIgnoreEl, folderIgnore.name, folderIgnore.description.replaceAll('\n', ' ')); - - // const setting = new Setting(containerEl) - // .addDropdown((dropdown) => { - // // First, add all the available options - // for (const option of this.options) { - // dropdown.addOption(option.value.replace('enums.', ''), option.getDisplayValue()); - // } - - // // Set currently selected value from existing settings - // dropdown.setValue(settings.ruleConfigs[this.ruleAlias][this.configKey]); - - // dropdown.onChange((value) => { - // this.setOption(value, settings); - // plugin.settings = settings; - // plugin.saveSettings(); - // }); - // }); - - // this.parseNameAndDescriptionAndRemoveSettingBorder(setting, plugin); } } diff --git a/src/ui/linter-components/auto-correct-files-picker-option.ts b/src/ui/linter-components/auto-correct-files-picker-option.ts index 0558afd7..f752aaac 100644 --- a/src/ui/linter-components/auto-correct-files-picker-option.ts +++ b/src/ui/linter-components/auto-correct-files-picker-option.ts @@ -3,6 +3,7 @@ import {LanguageStringKey, getTextInLanguage} from 'src/lang/helpers'; import {AddCustomRow} from '../components/add-custom-row'; import MdFileSuggester from '../suggesters/md-file-suggester'; import {parseCustomReplacements, stripCr} from '../../utils/strings'; +import {ParseResultsModal} from '../modals/parse-results-modal'; export type CustomAutoCorrectContent = {filePath: string, customReplacements: Map}; @@ -16,7 +17,7 @@ export class AutoCorrectFilesPickerOption extends AddCustomRow { getTextInLanguage(name), getTextInLanguage(description), null, - 'Add another custom file', + getTextInLanguage('options.custom-auto-correct.add-input-button-text'), saveSettings, ()=>{ this.selectedFiles = []; @@ -44,13 +45,12 @@ export class AutoCorrectFilesPickerOption extends AddCustomRow { const setting = new Setting(this.inputElDiv) .addSearch((cb) => { new MdFileSuggester(this.app, cb.inputEl, this.selectedFiles); - cb.setPlaceholder(getTextInLanguage('tabs.general.folders-to-ignore.folder-search-placeholder-text')) + cb.setPlaceholder(getTextInLanguage('options.custom-auto-correct.file-search-placeholder-text')) .setValue(pickedFile.filePath) .onChange(async (newPickedFile) => { const customReplacementFile = newPickedFile; if (customReplacementFile === '' || customReplacementFile === cb.inputEl.getAttribute('fileName')) { - console.log('getting file from path...'); const file = this.getFileFromPath(customReplacementFile); pickedFile.filePath = customReplacementFile; if (file) { @@ -59,7 +59,6 @@ export class AutoCorrectFilesPickerOption extends AddCustomRow { pickedFile.customReplacements = null; } - console.log(pickedFile); this.filesPicked[index] = pickedFile; this.saveSettings(); } @@ -72,9 +71,16 @@ export class AutoCorrectFilesPickerOption extends AddCustomRow { cb.inputEl.focus(); } }) + .addExtraButton((cb) => { + cb.setIcon('info') + .setTooltip(getTextInLanguage('options.custom-auto-correct.show-parsed-contents-tooltip')) + .onClick(() => { + new ParseResultsModal(this.app, pickedFile).open(); + }); + }) .addExtraButton((cb) => { cb.setIcon('cross') - .setTooltip(getTextInLanguage('tabs.general.folders-to-ignore.delete-tooltip')) + .setTooltip(getTextInLanguage('options.custom-auto-correct.delete-tooltip')) .onClick(() => { this.filesPicked.splice(index, 1); this.saveSettings(); diff --git a/src/ui/linter-components/tab-components/rule-tab.ts b/src/ui/linter-components/tab-components/rule-tab.ts index 8c85daac..76fe4ff2 100644 --- a/src/ui/linter-components/tab-components/rule-tab.ts +++ b/src/ui/linter-components/tab-components/rule-tab.ts @@ -23,12 +23,6 @@ export class RuleTab extends Tab { optionInfo.push(option.getSearchInfo()); } - // // add file picker for custom inputs to auto-correct-common-misspellings - // if (rule.alias === 'auto-correct-common-misspellings') { - - // } - - this.addSettingSearchInfo(ruleDiv, rule.getName().toLowerCase(), rule.getDescription().toLowerCase(), optionInfo, ruleDiv.id); } } diff --git a/src/ui/modals/lint-confirmation-modal.ts b/src/ui/modals/lint-confirmation-modal.ts index 42ce24b5..8cdfa241 100644 --- a/src/ui/modals/lint-confirmation-modal.ts +++ b/src/ui/modals/lint-confirmation-modal.ts @@ -18,7 +18,7 @@ export class LintConfirmationModal extends Modal { {text: startModalMessageText + ' ' + getTextInLanguage('file-backup-text')}).id = 'confirm-dialog'; this.contentEl.createDiv('modal-button-container', (buttonsEl) => { - buttonsEl.createEl('button', {text: 'Cancel'}).addEventListener('click', () => this.close()); + buttonsEl.createEl('button', {text: getTextInLanguage('cancel-button-text')}).addEventListener('click', () => this.close()); const btnSubmit = buttonsEl.createEl('button', { attr: {type: 'submit'}, diff --git a/src/ui/modals/parse-results-modal.ts b/src/ui/modals/parse-results-modal.ts new file mode 100644 index 00000000..82c912bc --- /dev/null +++ b/src/ui/modals/parse-results-modal.ts @@ -0,0 +1,33 @@ +import {Modal, App} from 'obsidian'; +import {getTextInLanguage} from 'src/lang/helpers'; +import {CustomAutoCorrectContent} from '../linter-components/auto-correct-files-picker-option'; + +// https://github.com/nothingislost/obsidian-workspaces-plus/blob/bbba928ec64b30b8dec7fe8fc9e5d2d96543f1f3/src/modal.ts#L68 +export class ParseResultsModal extends Modal { + constructor(app: App, customAutoCorrectionInfo: CustomAutoCorrectContent) { + super(app); + this.modalEl.addClass('confirm-modal'); + + this.contentEl.createEl('h3', {text: getTextInLanguage('parse-results-heading-text')}).style.textAlign = 'center'; + + this.contentEl.createEl('p', {text: getTextInLanguage('file-parse-description-text').replace('{FILE}', customAutoCorrectionInfo.filePath)}).id = 'confirm-dialog'; + + const tableEl = this.contentEl.createDiv().createEl('table', {cls: 'markdown-rendered'}); + const tableHeaderEl = tableEl.createEl('tr'); + tableHeaderEl.createEl('th', {text: getTextInLanguage('find-header-text')}); + tableHeaderEl.createEl('th', {text: getTextInLanguage('replace-header-text')}); + + let tableRow: HTMLElement; + for (const replacementInfo of customAutoCorrectionInfo.customReplacements) { + tableRow = tableEl.createEl('tr'); + tableRow.createEl('td', {text: replacementInfo[0]}); + tableRow.createEl('td', {text: replacementInfo[1]}); + } + + this.contentEl.createDiv('modal-button-container', (buttonsEl) => { + buttonsEl.createEl('button', {text: getTextInLanguage('close-button-text')}).addEventListener('click', () => this.close()); + }); + } +} + +// function createParseResultsTable(customAutoCorrectionInfo: CustomAutoCorrectContent) {} diff --git a/src/utils/strings.ts b/src/utils/strings.ts index 8ce6fc4b..ff050cee 100644 --- a/src/utils/strings.ts +++ b/src/utils/strings.ts @@ -1,4 +1,5 @@ import {calloutRegex, codeBlockBlockquoteRegex} from './regex'; +import {getTextInLanguage} from '../lang/helpers'; import {logWarn} from './logger'; import {getAllTablesInText} from './mdast'; /** @@ -524,8 +525,7 @@ export function parseCustomReplacements(text: string): Map { rowParts = row.split('|'); if (rowParts.length !== 4) { - // TODO: move this to en.ts - logWarn(`"${row}" is not a valid row with custom replacements. It must have only 2 columns.`); + logWarn(getTextInLanguage('options.custom-auto-correct.custom-row-parse-warning').replace('{ROW}', row)); continue; } From b7775199d7f61f5b02c743bf2d9cee547d4f5542 Mon Sep 17 00:00:00 2001 From: Peter Kaufman Date: Fri, 9 Aug 2024 21:40:19 -0400 Subject: [PATCH 05/10] removed some old logs --- src/option.ts | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/option.ts b/src/option.ts index c04ad5f3..9065a31b 100644 --- a/src/option.ts +++ b/src/option.ts @@ -180,9 +180,6 @@ export class MdFilePickerOption extends Option { } public display(containerEl: HTMLElement, settings: LinterSettings, plugin: LinterPlugin): void { - console.log(this.configKey); - console.log(settings.ruleConfigs[this.ruleAlias]); - console.log(settings.ruleConfigs[this.ruleAlias][this.configKey]); settings.ruleConfigs[this.ruleAlias][this.configKey] = settings.ruleConfigs[this.ruleAlias][this.configKey] ?? []; new AutoCorrectFilesPickerOption(containerEl, plugin.settingsTab.component, settings.ruleConfigs[this.ruleAlias][this.configKey], plugin.app, () => { From b228a77464788c3f5f34a49d4ea6aa2657866b96 Mon Sep 17 00:00:00 2001 From: Peter Kaufman Date: Fri, 9 Aug 2024 22:20:25 -0400 Subject: [PATCH 06/10] fixed the UTs to make sure they work and went ahead and added one for the scenario where we have custom mispellings --- __mocks__/obsidian.ts | 3 +++ .../auto-correct-common-misspellings.test.ts | 15 +++++++++++++++ src/rules/auto-correct-common-misspellings.ts | 1 + .../auto-correct-files-picker-option.ts | 2 +- src/ui/modals/parse-results-modal.ts | 2 +- 5 files changed, 21 insertions(+), 2 deletions(-) diff --git a/__mocks__/obsidian.ts b/__mocks__/obsidian.ts index e6bb2ed9..50bc4fbb 100644 --- a/__mocks__/obsidian.ts +++ b/__mocks__/obsidian.ts @@ -2,3 +2,6 @@ import moment from 'moment'; export {moment as moment}; + +// Needed to make sure that auto-correct tests work due to the auto-correct option using a modal in some scenarios +export class Modal {} diff --git a/__tests__/auto-correct-common-misspellings.test.ts b/__tests__/auto-correct-common-misspellings.test.ts index 469ad847..5e55b3a2 100644 --- a/__tests__/auto-correct-common-misspellings.test.ts +++ b/__tests__/auto-correct-common-misspellings.test.ts @@ -36,5 +36,20 @@ ruleTest({ ĂȘtre `, }, + { + testName: 'Custom replacements should work on file content', + before: dedent` + The cartt is over theree. + `, + after: dedent` + The cart is over there. + `, + options: { + extraAutoCorrectFiles: [{ + filePath: 'file_path', + customReplacements: new Map([['cartt', 'cart'], ['theree', 'there']]), + }], + }, + }, ], }); diff --git a/src/rules/auto-correct-common-misspellings.ts b/src/rules/auto-correct-common-misspellings.ts index df7359de..bd2203db 100644 --- a/src/rules/auto-correct-common-misspellings.ts +++ b/src/rules/auto-correct-common-misspellings.ts @@ -135,6 +135,7 @@ export default class AutoCorrectCommonMisspellings extends RuleBuilder Date: Sun, 11 Aug 2024 16:33:55 -0400 Subject: [PATCH 07/10] removed some ghost code, updated the custom parse modal to handle no entries found in a file, and handled no file selected for the view parsed contents extra button --- __tests__/parse-custom-replacements.test.ts | 77 +++++++++++++++++++ src/lang/locale/en.ts | 1 + .../auto-correct-files-picker-option.ts | 13 +++- src/ui/modals/parse-results-modal.ts | 25 +++--- 4 files changed, 104 insertions(+), 12 deletions(-) create mode 100644 __tests__/parse-custom-replacements.test.ts diff --git a/__tests__/parse-custom-replacements.test.ts b/__tests__/parse-custom-replacements.test.ts new file mode 100644 index 00000000..1bf1e8c7 --- /dev/null +++ b/__tests__/parse-custom-replacements.test.ts @@ -0,0 +1,77 @@ +import {parseCustomReplacements} from '../src/utils/strings'; +import dedent from 'ts-dedent'; + +type parseCustomReplacementsTestCase = { + name: string, + text: string, + expectedCustomReplacements: Map +}; + +const getTablesInTextTestCases: parseCustomReplacementsTestCase[] = [ + { + name: 'parsing a file with a single table with two columns gets the correct amount of parsed out entries', + text: dedent` + Here is some text + | column1 | column2 | + | ------- | ------- | + | replaceme | withme | + | replace | with | + `, + expectedCustomReplacements: new Map([['replaceme', 'withme'], ['replace', 'with']]), + }, + { + name: 'parsing a file with a single table with three columns gets no entries parsed out', + text: dedent` + Here is some text + | column1 | column2 | column3 | + | ------- | ------- | ---- | + | replaceme | withme | me | + | replace | with | me2 | + `, + expectedCustomReplacements: new Map(), + }, + { + name: 'parsing a file with two tables with two columns gets the correct amount of parsed out entries', + text: dedent` + Here is some text + | column1 | column2 | + | ------- | ------- | + | replaceme | withme | + | replace | with | + The following table also has some replacements + | header1 | header2 | + | ------- | ------- | + | var | variablE | + | hack | hacker | + `, + expectedCustomReplacements: new Map([['replaceme', 'withme'], ['replace', 'with'], ['var', 'variablE'], ['hack', 'hacker']]), + }, + { + name: 'parsing a file with no tables gets no parsed out entries', + text: dedent` + Here is some text without any tables in it. + `, + expectedCustomReplacements: new Map(), + }, + { + name: 'parsing a file with a single table with two columns gets no entries parsed out when each line is missing a pipe (i.e. |)', + text: dedent` + Here is some text + | column1 | column2 | + | ------- | ------- | + | replaceme | withme + replace | with | + `, + expectedCustomReplacements: new Map(), + }, +]; + +describe('Get All Tables in Text', () => { + for (const testCase of getTablesInTextTestCases) { + it(testCase.name, () => { + const customReplacements = parseCustomReplacements(testCase.text); + + expect(customReplacements).toEqual(testCase.expectedCustomReplacements); + }); + } +}); diff --git a/src/lang/locale/en.ts b/src/lang/locale/en.ts index 0381b1b2..c6af6940 100644 --- a/src/lang/locale/en.ts +++ b/src/lang/locale/en.ts @@ -111,6 +111,7 @@ export default { // parse-results-modal.ts 'parse-results-heading-text': 'Custom Parse Values', 'file-parse-description-text': 'The following is the list of custom replacements found in {FILE}.', + 'no-parsed-values-found-text': 'There were no custom replacements found in {FILE}. Please make sure that all tables with custom replacements in {FILE} only have two columns and all rows start and end with a pipe (i.e. |).', 'find-header-text': 'Word to Find', 'replace-header-text': 'Replacement Word', 'close-button-text': 'Close', diff --git a/src/ui/linter-components/auto-correct-files-picker-option.ts b/src/ui/linter-components/auto-correct-files-picker-option.ts index e6eaada8..9bea7cb3 100644 --- a/src/ui/linter-components/auto-correct-files-picker-option.ts +++ b/src/ui/linter-components/auto-correct-files-picker-option.ts @@ -1,4 +1,4 @@ -import {Setting, Component, App, TFile, normalizePath} from 'obsidian'; +import {Setting, Component, App, TFile, normalizePath, ExtraButtonComponent} from 'obsidian'; import {LanguageStringKey, getTextInLanguage} from '../../lang/helpers'; import {AddCustomRow} from '../components/add-custom-row'; import MdFileSuggester from '../suggesters/md-file-suggester'; @@ -42,6 +42,7 @@ export class AutoCorrectFilesPickerOption extends AddCustomRow { } private addPickedFile(pickedFile: CustomAutoCorrectContent, index: number, focusOnCommand: boolean = false) { + let showCustomParseContentButton: ExtraButtonComponent; const setting = new Setting(this.inputElDiv) .addSearch((cb) => { new MdFileSuggester(this.app, cb.inputEl, this.selectedFiles); @@ -55,8 +56,12 @@ export class AutoCorrectFilesPickerOption extends AddCustomRow { pickedFile.filePath = customReplacementFile; if (file) { pickedFile.customReplacements = parseCustomReplacements(stripCr(await this.app.vault.read(file))); + showCustomParseContentButton.disabled = false; + showCustomParseContentButton.extraSettingsEl.addClass('clickable-icon'); } else { + showCustomParseContentButton.disabled = true; pickedFile.customReplacements = null; + showCustomParseContentButton.extraSettingsEl.removeClass('clickable-icon'); } this.filesPicked[index] = pickedFile; @@ -72,11 +77,17 @@ export class AutoCorrectFilesPickerOption extends AddCustomRow { } }) .addExtraButton((cb) => { + showCustomParseContentButton = cb; cb.setIcon('info') .setTooltip(getTextInLanguage('options.custom-auto-correct.show-parsed-contents-tooltip')) .onClick(() => { new ParseResultsModal(this.app, pickedFile).open(); }); + + if (pickedFile.filePath === '') { + cb.disabled = true; + cb.extraSettingsEl.removeClass('clickable-icon'); + } }) .addExtraButton((cb) => { cb.setIcon('cross') diff --git a/src/ui/modals/parse-results-modal.ts b/src/ui/modals/parse-results-modal.ts index 5923e31c..ac9ccd3d 100644 --- a/src/ui/modals/parse-results-modal.ts +++ b/src/ui/modals/parse-results-modal.ts @@ -10,18 +10,22 @@ export class ParseResultsModal extends Modal { this.contentEl.createEl('h3', {text: getTextInLanguage('parse-results-heading-text')}).style.textAlign = 'center'; - this.contentEl.createEl('p', {text: getTextInLanguage('file-parse-description-text').replace('{FILE}', customAutoCorrectionInfo.filePath)}).id = 'confirm-dialog'; + if (customAutoCorrectionInfo?.customReplacements.size > 0) { + this.contentEl.createEl('p', {text: getTextInLanguage('file-parse-description-text').replace('{FILE}', customAutoCorrectionInfo.filePath)}).id = 'confirm-dialog'; - const tableEl = this.contentEl.createDiv().createEl('table', {cls: 'markdown-rendered'}); - const tableHeaderEl = tableEl.createEl('tr'); - tableHeaderEl.createEl('th', {text: getTextInLanguage('find-header-text')}); - tableHeaderEl.createEl('th', {text: getTextInLanguage('replace-header-text')}); + const tableEl = this.contentEl.createDiv().createEl('table', {cls: 'markdown-rendered'}); + const tableHeaderEl = tableEl.createEl('tr'); + tableHeaderEl.createEl('th', {text: getTextInLanguage('find-header-text')}); + tableHeaderEl.createEl('th', {text: getTextInLanguage('replace-header-text')}); - let tableRow: HTMLElement; - for (const replacementInfo of customAutoCorrectionInfo.customReplacements) { - tableRow = tableEl.createEl('tr'); - tableRow.createEl('td', {text: replacementInfo[0]}); - tableRow.createEl('td', {text: replacementInfo[1]}); + let tableRow: HTMLElement; + for (const replacementInfo of customAutoCorrectionInfo.customReplacements) { + tableRow = tableEl.createEl('tr'); + tableRow.createEl('td', {text: replacementInfo[0]}); + tableRow.createEl('td', {text: replacementInfo[1]}); + } + } else { + this.contentEl.createEl('p', {text: getTextInLanguage('no-parsed-values-found-text').replaceAll('{FILE}', customAutoCorrectionInfo.filePath)}).style.fontWeight = 'bold'; } this.contentEl.createDiv('modal-button-container', (buttonsEl) => { @@ -30,4 +34,3 @@ export class ParseResultsModal extends Modal { } } -// function createParseResultsTable(customAutoCorrectionInfo: CustomAutoCorrectContent) {} From f9143c6b82472ac0b1eafe347b08d115057a886f Mon Sep 17 00:00:00 2001 From: Peter Kaufman Date: Sun, 11 Aug 2024 16:52:20 -0400 Subject: [PATCH 08/10] added extra docs for how to use common mispellings --- .../rules/auto-correct-common-misspellings.md | 31 +++++++++++++++++++ 1 file changed, 31 insertions(+) create mode 100644 docs/additional-info/rules/auto-correct-common-misspellings.md diff --git a/docs/additional-info/rules/auto-correct-common-misspellings.md b/docs/additional-info/rules/auto-correct-common-misspellings.md new file mode 100644 index 00000000..f5fa10d0 --- /dev/null +++ b/docs/additional-info/rules/auto-correct-common-misspellings.md @@ -0,0 +1,31 @@ +#### How to Use Custom Misspellings + +There is a default list of common misspellings that is used as the base for how this rule works. +However, there may be instances where the user may want to add their own list of misspellings to handle. +In those scenarios, they can add files to the list of files that have custom misspellings in them. + +##### Format + +A file that has custom misspellings in them can have any content in them. But the only content that will +be parsed as custom misspellings should be found in a two column table. For example the following table +will result in `th` being replaced with `the` and `tht` being replaced with `that`: + +``` markdown +The following is a table with custom misspellings: +| Replace | With | +| ------- | ---- | +| th | the | +| tht | that | +``` + +!!! Note + The first two lines of the table are skipped (the header and separator) and all rows after that + must start and end with a pipe (`|`). If any do not start or end with a pipe or they have more + than 2 columns, then they will be skipped. + +##### Current Limitations + +- The list of custom replacements is only loaded when the plugin initially loads or when the file is added to the list of files that include custom misspellings + - This means that making a change to a file that is already in the list of custom misspelling files will not work unless the Linter is reloaded or the file is removed and re-added to the list of custom misspelling files +- There is no way to specify that a word is to always be capitalized + - This is due to how the auto-correct rule was designed as it sets the first letter of the replacement word to the case of the first letter of the word being replaced From 9ce2249fb5a8ea5f150f560c9199e3749eef6549 Mon Sep 17 00:00:00 2001 From: Peter Kaufman Date: Sun, 11 Aug 2024 17:03:51 -0400 Subject: [PATCH 09/10] fixed the esbuild for docs --- docs/docs/settings/content-rules.md | 35 +++++++++++++++++++++++++++++ esbuild.config.mjs | 10 +++++++++ 2 files changed, 45 insertions(+) diff --git a/docs/docs/settings/content-rules.md b/docs/docs/settings/content-rules.md index b5519629..35252e73 100644 --- a/docs/docs/settings/content-rules.md +++ b/docs/docs/settings/content-rules.md @@ -15,7 +15,42 @@ Uses a dictionary of common misspellings to automatically convert them to their | Name | Description | List Items | Default Value | | ---- | ----------- | ---------- | ------------- | | `Ignore Words` | A comma separated list of lowercased words to ignore when auto-correcting | N/A | | +| `Extra Auto-Correct Source Files` | These are files that have a markdown table in them that have the initial word and the word to correct it to (these are case insensitive corrections). **Note: the tables used should have the starting and ending `|` indicators present for each line.** | N/A | | +### Additional Info + + +#### How to Use Custom Misspellings + +There is a default list of common misspellings that is used as the base for how this rule works. +However, there may be instances where the user may want to add their own list of misspellings to handle. +In those scenarios, they can add files to the list of files that have custom misspellings in them. + +##### Format + +A file that has custom misspellings in them can have any content in them. But the only content that will +be parsed as custom misspellings should be found in a two column table. For example the following table +will result in `th` being replaced with `the` and `tht` being replaced with `that`: + +``` markdown +The following is a table with custom misspellings: +| Replace | With | +| ------- | ---- | +| th | the | +| tht | that | +``` + +!!! Note + The first two lines of the table are skipped (the header and separator) and all rows after that + must start and end with a pipe (`|`). If any do not start or end with a pipe or they have more + than 2 columns, then they will be skipped. + +##### Current Limitations + +- The list of custom replacements is only loaded when the plugin initially loads or when the file is added to the list of files that include custom misspellings + - This means that making a change to a file that is already in the list of custom misspelling files will not work unless the Linter is reloaded or the file is removed and re-added to the list of custom misspelling files +- There is no way to specify that a word is to always be capitalized + - This is due to how the auto-correct rule was designed as it sets the first letter of the replacement word to the case of the first letter of the word being replaced ### Examples diff --git a/esbuild.config.mjs b/esbuild.config.mjs index 87228e54..958d373b 100644 --- a/esbuild.config.mjs +++ b/esbuild.config.mjs @@ -28,6 +28,16 @@ const mockedPlugins = [replace({ 'import {Setting} from \'obsidian\';': '', // remove the use of obsidian in settings helper to allow for docs.js to run 'import {Component, MarkdownRenderer} from \'obsidian\';': '', + // remove the use of obsidian in the auto-correct files picker to allow for docs.js to run + 'import {Setting, Component, App, TFile, normalizePath, ExtraButtonComponent} from \'obsidian\';': '', + // remove the use of obsidian in add custom row to allow for docs.js to run + 'import {Component, Setting} from \'obsidian\';': '', + // remove the use of obsidian in suggest to allow for docs.js to run + 'import {App, ISuggestOwner, Scope} from \'obsidian\';': '', + // remove the use of obsidian in md file suggester to allow for docs.js to run + 'import {App, TFile} from \'obsidian\';': '', + // remove the use of obsidian in parse results modal to allow for docs.js to run + 'import {Modal, App} from \'obsidian\';': 'class Modal {}', }, delimiters: ['', ''], })]; From 358b8bb79b45d7297eccbb539ccff47b300c5b76 Mon Sep 17 00:00:00 2001 From: Peter Kaufman Date: Sun, 11 Aug 2024 17:10:21 -0400 Subject: [PATCH 10/10] got nested lists showing up correctly --- .../rules/auto-correct-common-misspellings.md | 5 +++-- docs/docs/settings/content-rules.md | 5 +++-- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/docs/additional-info/rules/auto-correct-common-misspellings.md b/docs/additional-info/rules/auto-correct-common-misspellings.md index f5fa10d0..1161e3aa 100644 --- a/docs/additional-info/rules/auto-correct-common-misspellings.md +++ b/docs/additional-info/rules/auto-correct-common-misspellings.md @@ -25,7 +25,8 @@ The following is a table with custom misspellings: ##### Current Limitations + - The list of custom replacements is only loaded when the plugin initially loads or when the file is added to the list of files that include custom misspellings - - This means that making a change to a file that is already in the list of custom misspelling files will not work unless the Linter is reloaded or the file is removed and re-added to the list of custom misspelling files + * This means that making a change to a file that is already in the list of custom misspelling files will not work unless the Linter is reloaded or the file is removed and re-added to the list of custom misspelling files - There is no way to specify that a word is to always be capitalized - - This is due to how the auto-correct rule was designed as it sets the first letter of the replacement word to the case of the first letter of the word being replaced + - This is due to how the auto-correct rule was designed as it sets the first letter of the replacement word to the case of the first letter of the word being replaced diff --git a/docs/docs/settings/content-rules.md b/docs/docs/settings/content-rules.md index 35252e73..fd9a1bba 100644 --- a/docs/docs/settings/content-rules.md +++ b/docs/docs/settings/content-rules.md @@ -47,10 +47,11 @@ The following is a table with custom misspellings: ##### Current Limitations + - The list of custom replacements is only loaded when the plugin initially loads or when the file is added to the list of files that include custom misspellings - - This means that making a change to a file that is already in the list of custom misspelling files will not work unless the Linter is reloaded or the file is removed and re-added to the list of custom misspelling files + * This means that making a change to a file that is already in the list of custom misspelling files will not work unless the Linter is reloaded or the file is removed and re-added to the list of custom misspelling files - There is no way to specify that a word is to always be capitalized - - This is due to how the auto-correct rule was designed as it sets the first letter of the replacement word to the case of the first letter of the word being replaced + - This is due to how the auto-correct rule was designed as it sets the first letter of the replacement word to the case of the first letter of the word being replaced ### Examples