/* THIS IS A GENERATED/BUNDLED FILE BY ESBUILD if you want to view the source, please visit the github repository of this plugin */ var __defProp = Object.defineProperty; var __getOwnPropDesc = Object.getOwnPropertyDescriptor; var __getOwnPropNames = Object.getOwnPropertyNames; var __hasOwnProp = Object.prototype.hasOwnProperty; var __export = (target, all) => { for (var name in all) __defProp(target, name, { get: all[name], enumerable: true }); }; var __copyProps = (to, from, except, desc) => { if (from && typeof from === "object" || typeof from === "function") { for (let key of __getOwnPropNames(from)) if (!__hasOwnProp.call(to, key) && key !== except) __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable }); } return to; }; var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod); // main.ts var main_exports = {}; __export(main_exports, { default: () => SpellcheckTogglerPlugin }); module.exports = __toCommonJS(main_exports); // src/plugin.ts var import_obsidian2 = require("obsidian"); // src/settings.ts var import_obsidian = require("obsidian"); var SpellcheckBehaviourOptionDisplay = { ["default" /* DEFAULT */]: "Always spellcheck", ["frontmatter" /* FRONTMATTER */]: "Use frontmatter", ["global" /* GLOBAL */]: "Never spellcheck" }; var defaultSettings = { externalLinks: { behaviour: "global" /* GLOBAL */ }, internalLinks: { behaviour: "global" /* GLOBAL */ }, bareLinks: { behaviour: "global" /* GLOBAL */ }, htmlComments: { behaviour: "default" /* DEFAULT */ }, anyNode: { behaviour: "default" /* DEFAULT */ }, emphasis: { behaviour: "default" /* DEFAULT */ }, strong: { behaviour: "default" /* DEFAULT */ }, blockquote: { behaviour: "default" /* DEFAULT */ } }; var SpellcheckTogglerSettingTab = class extends import_obsidian.PluginSettingTab { constructor(app, plugin) { super(app, plugin); this.plugin = plugin; } display() { let { containerEl } = this; containerEl.empty(); const createSpellcheckOptionDisplay = (optionKey, name, description, targetFormat) => { const settingContainer = containerEl.createDiv({ cls: "settings-container" }); const headingSetting = new import_obsidian.Setting(settingContainer).setHeading().setName(name).setDesc(description); if (targetFormat) { const span = headingSetting.controlEl.createEl("span", { text: `Targeted format: `, cls: "setting-item-target-label" }); span.createEl("code", { text: targetFormat, cls: "setting-item-target-label" }); } const frontmatterDrawer = settingContainer.createDiv({ cls: "frontmatter-drawer" }); new import_obsidian.Setting(frontmatterDrawer).setName("Frontmatter override property").setDesc( "Define the (boolean) frontmatter property which controls the spellcheck behaviour for a file." ).addText( (text) => { var _a; return text.setValue( (_a = this.plugin.settings[optionKey].frontmatterOverride) != null ? _a : "" ).onChange( (frontmatterOverride) => this.plugin.saveSettings({ [optionKey]: { ...this.plugin.settings[optionKey], frontmatterOverride: frontmatterOverride.length ? frontmatterOverride : void 0 } }) ); } ); new import_obsidian.Setting(frontmatterDrawer).setName("Fallback behavior").setDesc( "Select the spellcheck fallback behavior for the node in files where the frontmatter property is absent." ).addDropdown((dropdown) => { var _a; const { frontmatter, ...filteredOptions } = SpellcheckBehaviourOptionDisplay; dropdown.addOptions({ ...filteredOptions }).onChange((frontmatterFallback) => { this.plugin.saveSettings({ [optionKey]: { ...this.plugin.settings[optionKey], frontmatterFallback } }); }).setValue( (_a = this.plugin.settings[optionKey].frontmatterFallback) != null ? _a : "default" /* DEFAULT */ ); }); frontmatterDrawer.toggleClass( "hidden", [ "default" /* DEFAULT */, "global" /* GLOBAL */ ].includes(this.plugin.settings[optionKey].behaviour) ); new import_obsidian.Setting(settingContainer).setName("Spellchecking behaviour").addDropdown( (dropdown) => dropdown.addOptions(SpellcheckBehaviourOptionDisplay).onChange((behaviour) => { this.plugin.saveSettings({ [optionKey]: { ...this.plugin.settings[optionKey], behaviour } }); frontmatterDrawer.toggleClass( "hidden", [ "default" /* DEFAULT */, "global" /* GLOBAL */ ].includes( this.plugin.settings[optionKey].behaviour ) ); }).setValue(this.plugin.settings[optionKey].behaviour) ); settingContainer.appendChild(frontmatterDrawer); }; const legendContainer = containerEl.createDiv({ cls: "settings-container" }); new import_obsidian.Setting(legendContainer).setHeading().setName("Spellcheck toggler settings").setDesc( "Configure spellchecking options. The behaviour of a spellcheck option is defined as follows:" ); const list = legendContainer.createEl("ul"); list.createEl("li", { text: ` "Always spellcheck": the editor default behaviour will be applied (the plugin is not active for the option).`, cls: "setting-item-target-label" }); list.createEl("li", { text: ` "Use frontmatter": use the defined frontmatter property to toggle spellchecking per file.`, cls: "setting-item-target-label" }); list.createEl("li", { text: ` "Never spellcheck": do not use spellcheck in any file for the option.`, cls: "setting-item-target-label" }); createSpellcheckOptionDisplay( "externalLinks", "Markdown links option", "Toggle spellcheck underline for link text in any markdown link.", "![text](link)" ); createSpellcheckOptionDisplay( "internalLinks", "Wikilinks option", "Toggle spellcheck underline for link text in any wikilink.", "[[ link text ]]" ); createSpellcheckOptionDisplay( "bareLinks", "Bare links option", "Toggle spellcheck underline for text in any bare link.", "[text]" ); createSpellcheckOptionDisplay( "htmlComments", "Html comment option", "Toggle spellcheck underline for any text inside an html comment block.", "<-- text -->" ); createSpellcheckOptionDisplay( "blockquote", "Blockquote node option", "Toggle spellcheck for text inside block quotes.", ">text" ); createSpellcheckOptionDisplay( "emphasis", "Italics (emphasis) node option", "Toggle spellcheck for italics (emphasis) text.", "*text*" ); createSpellcheckOptionDisplay( "strong", "Bolded (strong) node option", "Toggle spellcheck for bolded (strong) text.", "**text**" ); createSpellcheckOptionDisplay( "anyNode", "Per file option", 'Toggle spellcheck for an entire file. With "Never spellcheck", spellchecking is disabled for all files.', "*" ); } }; // src/spellchecks/html-comments.ts var import_view2 = require("@codemirror/view"); // src/spellchecks/apply-spellcheck-plugin.ts var import_view = require("@codemirror/view"); var import_state = require("@codemirror/state"); var import_language = require("@codemirror/language"); // src/context.ts var spellcheckContext = { file: null, frontmatter: null, settings: defaultSettings, uniqueOverrideKeys: [] }; var updateSpellcheckContext = (partialContext) => { if ("frontmatter" in partialContext) { updateFrontmatterWithDifference(partialContext.frontmatter); delete partialContext["frontmatter"]; } if ("settings" in partialContext) { spellcheckContext.uniqueOverrideKeys = Object.values( partialContext.settings ).reduce((set, option) => { const override = option.frontmatterOverride; if (override !== void 0) set.push(override); return set; }, []); } spellcheckContext = { ...spellcheckContext, ...partialContext }; }; var updateFrontmatterWithDifference = (frontmatter) => { if (frontmatter === null) { spellcheckContext.frontmatter = null; return true; } const frontmatterSpellcheckKeys = Object.keys(frontmatter).filter( (k) => spellcheckContext.uniqueOverrideKeys.includes(k) ); const filteredFrontmatter = frontmatterSpellcheckKeys.reduce((ffm, k) => { ffm[k] = frontmatter[k]; return ffm; }, {}); if (spellcheckContext.frontmatter === null || Object.keys(spellcheckContext.frontmatter).length !== frontmatterSpellcheckKeys.length) { spellcheckContext.frontmatter = filteredFrontmatter; return true; } for (const key of frontmatterSpellcheckKeys) { if (key in spellcheckContext.frontmatter && spellcheckContext.frontmatter[key] === frontmatter[key]) continue; spellcheckContext.frontmatter = filteredFrontmatter; return true; } return false; }; var getSpellcheckContextProperty = (key) => spellcheckContext[key]; // src/spellchecks/apply-spellcheck-plugin.ts var ApplySpellcheckAttributePluginValue = class { constructor(view) { this.decorations = this.buildDecorations(view); } update(update) { if (!update.docChanged && !update.viewportChanged) return; this.decorations = this.buildDecorations(update.view); } buildDecorations(view) { const builder = new import_state.RangeSetBuilder(); const markSpellcheckFalse = import_view.Decoration.mark({ attributes: { spellcheck: "false" } }); const adds = []; const enter = (node) => { var _a; if ((_a = this.isNodeEligible) == null ? void 0 : _a.call(this, node)) adds.push({ from: node.from, to: node.to }); }; for (let { from, to } of view.visibleRanges) (0, import_language.syntaxTree)(view.state).iterate({ from, to, enter }); adds.sort((a, b) => a.from - b.from); for (const { from, to } of adds) builder.add(from, to, markSpellcheckFalse); return builder.finish(); } }; var checkNodeEligibility = (settingsKey) => { const frontmatter = getSpellcheckContextProperty("frontmatter"); switch (getSpellcheckContextProperty("settings")[settingsKey].behaviour) { case "default" /* DEFAULT */: return false; case "global" /* GLOBAL */: return true; case "frontmatter" /* FRONTMATTER */: const override = getSpellcheckContextProperty("settings")[settingsKey].frontmatterOverride; const isOverrideInFrontmatter = frontmatter !== null && override !== void 0 && override in frontmatter; const fallback = getSpellcheckContextProperty("settings")[settingsKey].frontmatterFallback; const isOverrideFalse = isOverrideInFrontmatter && frontmatter[override] === false; const isFallbackDisable = !isOverrideInFrontmatter && fallback === "global" /* GLOBAL */; return isOverrideFalse || isFallbackDisable; } return false; }; // src/spellchecks/html-comments.ts var HtmlCommentSpellcheckPluginValue = class extends ApplySpellcheckAttributePluginValue { isNodeEligible(node) { if (!node.type.name.startsWith("comment")) return false; return checkNodeEligibility("htmlComments"); } }; var htmlCommentSpellcheckPluginValue = import_view2.ViewPlugin.fromClass( HtmlCommentSpellcheckPluginValue, { decorations: (pluginValue) => pluginValue.decorations } ); // src/spellchecks/markdown-links.ts var import_view3 = require("@codemirror/view"); var MarkdownLinkSpellcheckPluginValue = class extends ApplySpellcheckAttributePluginValue { isNodeEligible(node) { if (node.type.name.match(/^link|.*_link$/) === null || node.type.name.contains("hmd-barelink")) return false; return checkNodeEligibility("externalLinks"); } }; var markdownLinkSpellcheckViewPlugin = import_view3.ViewPlugin.fromClass( MarkdownLinkSpellcheckPluginValue, { decorations: (pluginValue) => pluginValue.decorations } ); // src/spellchecks/wiki-links.ts var import_view4 = require("@codemirror/view"); var WikiLinkSpellcheckPluginValue = class extends ApplySpellcheckAttributePluginValue { isNodeEligible(node) { if (!node.type.name.contains("hmd-internal-link")) return false; return checkNodeEligibility("internalLinks"); } }; var wikiLinkSpellcheckViewPlugin = import_view4.ViewPlugin.fromClass( WikiLinkSpellcheckPluginValue, { decorations: (pluginValue) => pluginValue.decorations } ); // src/spellchecks/emphasis.ts var import_view5 = require("@codemirror/view"); var EmphasisSpellcheckPluginValue = class extends ApplySpellcheckAttributePluginValue { isNodeEligible(node) { if (!node.type.name.startsWith("em")) return false; return checkNodeEligibility("emphasis"); } }; var emphasisSpellcheckPluginValue = import_view5.ViewPlugin.fromClass( EmphasisSpellcheckPluginValue, { decorations: (pluginValue) => pluginValue.decorations } ); // src/spellchecks/strong.ts var import_view6 = require("@codemirror/view"); var StrongSpellcheckPluginValue = class extends ApplySpellcheckAttributePluginValue { isNodeEligible(node) { if (!node.type.name.startsWith("strong")) return false; return checkNodeEligibility("strong"); } }; var strongSpellcheckPluginValue = import_view6.ViewPlugin.fromClass( StrongSpellcheckPluginValue, { decorations: (pluginValue) => pluginValue.decorations } ); // src/migration/index.ts var validateAndMigrateSettings = (settings) => { if (settings === null) return {}; const keys1_1_0ToKeys1_2_0 = { spellcheckExternalLinks: "externalLinks", spellcheckInternalLinks: "internalLinks", spellcheckHtmlComments: "htmlComments" }; for (const [srcKey, destKey] of Object.entries(keys1_1_0ToKeys1_2_0)) { if (srcKey in settings && typeof settings[srcKey] === "boolean") { settings[destKey] = { behaviour: settings[srcKey] ? "default" /* DEFAULT */ : "global" /* GLOBAL */ }; delete settings[srcKey]; } } for (const [spellcheckKey, spellcheckOption] of Object.entries(settings)) { const behaviour = spellcheckOption["behaviour"]; if (["opt-in", "opt-out"].includes(behaviour)) { settings[spellcheckKey] = { behaviour: "frontmatter" /* FRONTMATTER */, frontmatterOverride: spellcheckOption["frontmatterOverride"], frontmatterFallback: behaviour === "opt-in" ? "default" /* DEFAULT */ : "global" /* GLOBAL */ }; } } return { ...settings }; }; // src/spellchecks/blockquote.ts var import_view7 = require("@codemirror/view"); var BlockQuoteSpellcheckPluginValue = class extends ApplySpellcheckAttributePluginValue { isNodeEligible(node) { if (!node.type.name.startsWith("quote")) return false; return checkNodeEligibility("blockquote"); } }; var blockQuoteSpellcheckPluginValue = import_view7.ViewPlugin.fromClass( BlockQuoteSpellcheckPluginValue, { decorations: (pluginValue) => pluginValue.decorations } ); // src/spellchecks/barelink.ts var import_view8 = require("@codemirror/view"); var BareLinkSpellcheckPluginValue = class extends ApplySpellcheckAttributePluginValue { isNodeEligible(node) { if (!node.type.name.contains("hmd-barelink_link")) return false; return checkNodeEligibility("bareLinks"); } }; var bareLinkSpellcheckPluginValue = import_view8.ViewPlugin.fromClass( BareLinkSpellcheckPluginValue, { decorations: (pluginValue) => pluginValue.decorations } ); // src/plugin.ts var SpellcheckTogglerPlugin = class extends import_obsidian2.Plugin { constructor() { super(...arguments); this.editorExtensions = []; } async loadSettings() { const userSettings = validateAndMigrateSettings(await this.loadData()); this.settings = { ...defaultSettings, ...userSettings }; this.saveData(this.settings); updateSpellcheckContext({ settings: this.settings }); } async saveSettings(settings) { this.settings = { ...this.settings, ...settings }; await this.saveData(this.settings); updateSpellcheckContext({ settings: this.settings }); this.refreshExtensions(); } buildExtensions() { this.editorExtensions.length = 0; if (this.settings.internalLinks.behaviour !== "default" /* DEFAULT */) this.editorExtensions.push(wikiLinkSpellcheckViewPlugin); if (this.settings.externalLinks.behaviour !== "default" /* DEFAULT */) this.editorExtensions.push(markdownLinkSpellcheckViewPlugin); if (this.settings.bareLinks.behaviour !== "default" /* DEFAULT */) this.editorExtensions.push(bareLinkSpellcheckPluginValue); if (this.settings.htmlComments.behaviour !== "default" /* DEFAULT */) this.editorExtensions.push(htmlCommentSpellcheckPluginValue); if (this.settings.blockquote.behaviour !== "default" /* DEFAULT */) this.editorExtensions.push(blockQuoteSpellcheckPluginValue); if (this.settings.emphasis.behaviour !== "default" /* DEFAULT */) this.editorExtensions.push(emphasisSpellcheckPluginValue); if (this.settings.strong.behaviour !== "default" /* DEFAULT */) this.editorExtensions.push(strongSpellcheckPluginValue); } refreshExtensions() { var _a, _b; this.buildExtensions(); this.app.workspace.updateOptions(); (_b = (_a = this.app.workspace.activeEditor) == null ? void 0 : _a.editor) == null ? void 0 : _b.refresh(); } handleSpellcheckAttribute() { let globalSpellcheckFlag = true; const anyNodeOption = getSpellcheckContextProperty("settings")["anyNode"]; switch (anyNodeOption.behaviour) { case "global" /* GLOBAL */: globalSpellcheckFlag = false; break; case "frontmatter" /* FRONTMATTER */: const frontmatter = getSpellcheckContextProperty("frontmatter"); const isOverrideInFrontmatter = frontmatter !== null && anyNodeOption.frontmatterOverride !== void 0 && anyNodeOption.frontmatterOverride in frontmatter; const isOverrideTrue = isOverrideInFrontmatter && frontmatter[anyNodeOption.frontmatterOverride] === true; const isFallbackDefault = !isOverrideInFrontmatter && anyNodeOption.frontmatterFallback !== "global" /* GLOBAL */; globalSpellcheckFlag = isOverrideTrue || isFallbackDefault; break; } const content = this.app.workspace.containerEl.querySelector(".cm-content"); const attributeObserver = new MutationObserver((_, observer) => { content.setAttribute("spellcheck", String(globalSpellcheckFlag)); observer.disconnect(); }); content.setAttribute("spellcheck", String(globalSpellcheckFlag)); attributeObserver.observe(content, { attributes: true, attributeOldValue: true, attributeFilter: ["spellcheck"] }); } onFileOpen(file) { var _a; if (file === null) return; const metadata = this.app.metadataCache.getFileCache(file); const frontmatter = (_a = metadata == null ? void 0 : metadata.frontmatter) != null ? _a : null; updateSpellcheckContext({ file, frontmatter }); this.handleSpellcheckAttribute(); } onFileModify(file) { var _a; if (file === null || ((_a = this.app.workspace.getActiveFile()) == null ? void 0 : _a.basename) !== file.basename) return; (async () => { var _a2; const content = await this.app.vault.cachedRead(file); const frontmatterInfo = (0, import_obsidian2.getFrontMatterInfo)(content); if (!frontmatterInfo.exists) return; const overrideKeys = getSpellcheckContextProperty("uniqueOverrideKeys"); const frontmatter = {}; for (const line of frontmatterInfo.frontmatter.split("\n")) { const [property, value] = line.split(":").map((s) => s.trim()); if (value === void 0 || value.length === 0) continue; const parsedValue = value === "true" ? true : value === "false" ? false : void 0; if (parsedValue !== void 0 && overrideKeys.includes(property)) frontmatter[property] = parsedValue; } const didDiffer = updateFrontmatterWithDifference(frontmatter); if (!didDiffer) return; this.handleSpellcheckAttribute(); const editor = (_a2 = this.app.workspace.activeEditor) == null ? void 0 : _a2.editor; if (!editor) return; editor.refresh(); })(); } async onload() { await this.loadSettings(); this.addSettingTab(new SpellcheckTogglerSettingTab(this.app, this)); this.buildExtensions(); this.registerEditorExtension(this.editorExtensions); this.onFileOpen(this.app.workspace.getActiveFile()); this.onFileOpenEventRef = this.app.workspace.on( "file-open", this.onFileOpen.bind(this) ); this.onFileModifyEventRef = this.app.vault.on( "modify", this.onFileModify.bind(this) ); } unload() { this.app.workspace.offref(this.onFileOpenEventRef); this.app.vault.offref(this.onFileModifyEventRef); super.unload(); } }; /* nosourcemap */