/* 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); // src/main.ts var main_exports = {}; __export(main_exports, { default: () => MathInCalloutPlugin }); module.exports = __toCommonJS(main_exports); var import_obsidian3 = require("obsidian"); // src/decorations.ts var import_state2 = require("@codemirror/state"); var import_language2 = require("@codemirror/language"); var import_view = require("@codemirror/view"); var import_obsidian = require("obsidian"); // src/quote-field.ts var import_language = require("@codemirror/language"); var import_state = require("@codemirror/state"); var QuoteInfo = class extends import_state.RangeValue { /** * @param level The level of the blockquote/callout (i.e. the number of ">"s). * @param isBaseCallout True if this is a callout or this is nested inside a callout of level 1. */ constructor(level, isBaseCallout) { super(); this.level = level; this.isBaseCallout = isBaseCallout; this.pattern = this.level > 0 ? new RegExp(`^( {0,3}>){${this.level}}`) : null; } eq(other) { return this.level === other.level && this.isBaseCallout === other.isBaseCallout; } /** Remove ">"s that is misrecognized as inequality signs. */ correctMath(math) { if (!this.pattern) return math; const lines = math.split("\n"); return lines.map((line) => { const match = line.match(this.pattern); return match ? line.slice(match[0].length) : line; }).join("\n"); } getBlockquoteBorderPositions(state, from, to) { const positions = []; const lineBegin = state.doc.lineAt(from); const lineEnd = state.doc.lineAt(to); for (let i = lineBegin.number; i <= lineEnd.number; i++) { const line = state.doc.line(i); let start = 0; for (let i2 = 0; i2 < this.level; i2++) { const index = line.text.indexOf(">", start); if (index === -1) continue; positions.push({ pos: index + line.from, first: i2 === 0 }); start = index + 1; } } return positions; } }; var quoteInfoField = import_state.StateField.define({ create(state) { return parseBlockquotes(state); }, update(prev, tr) { return tr.docChanged ? parseBlockquotes(tr.state) : prev; } }); function parseBlockquotes(state) { const tree = (0, import_language.syntaxTree)(state); const builder = new import_state.RangeSetBuilder(); let level = 0; let from = -1; let isBaseCallout = false; for (let i = 1; i <= state.doc.lines; i++) { const line = state.doc.line(i); const match = line.text.match(/^( {0,3}>)+/); const newLevel = match ? match[0].split(">").length - 1 : 0; if (newLevel !== level) { if (level === 0 && newLevel === 1) { isBaseCallout = tree.cursorAt(line.from, 1).node.name.contains("-callout"); } if (level > 0 && from >= 0) { builder.add(from, line.from, new QuoteInfo(level, isBaseCallout)); } level = newLevel; from = line.from; } } if (level > 0 && from >= 0) { builder.add(from, state.doc.length, new QuoteInfo(level, isBaseCallout)); } return builder.finish(); } // src/utils.ts function getQuoteInfo(state, pos) { const field = state.field(quoteInfoField, false); if (!field) return null; const { from, to, value } = field.iter(pos); if (from <= pos && pos <= to) return value; return null; } function hasOverlap(range, start, to) { return range.from <= to && range.to >= start; } function rangesHaveOverlap(ranges, start, to) { for (const range of ranges) { if (hasOverlap(range, start, to)) return true; } return false; } // src/decorations.ts var createCalloutDecorator = (BuiltInMathWidget) => import_state2.StateField.define({ create() { return import_view.Decoration.none; }, update(prev, tr) { const { state } = tr; const view = state.field(import_obsidian.editorEditorField); if (view.composing) return prev.map(tr.changes); const isSourceMode = !state.field(import_obsidian.editorLivePreviewField); const doc = state.doc; const ranges = view.hasFocus ? state.selection.ranges : []; const tree = (0, import_language2.syntaxTree)(state); const decorations = []; const makeDeco = (decorationSpec, from, to) => { if (decorationSpec.block && to === doc.length) decorationSpec.inclusiveEnd = false; return import_view.Decoration.replace(decorationSpec); }; let mathBegin = -1; let mathContentBegin = -1; let block = false; tree.iterate({ enter(node) { if (node.name.contains("formatting-math-begin")) { mathBegin = node.from; mathContentBegin = node.to; block = node.name.contains("math-block"); } else if (mathBegin !== -1) { if (node.name.contains("formatting-math-end")) { const mathContentEnd = node.from; const mathEnd = node.to; let math = doc.sliceString(mathContentBegin, mathContentEnd); const quote = getQuoteInfo(state, mathContentBegin); if (quote) math = quote.correctMath(math); const widget = new BuiltInMathWidget(math, block); if (quote) widget.markAsCorrected(); widget.setPos( block && math.startsWith("\n") ? mathContentBegin + 1 : mathContentBegin, block && math.endsWith("\n") ? mathContentEnd - 1 : mathContentEnd ); const overlap = rangesHaveOverlap(ranges, mathBegin, mathEnd); if (block && quote && quote.level > 0) { if (isSourceMode || quote.isBaseCallout || overlap) { const lineBegin = state.doc.lineAt(mathBegin); const lineEnd = state.doc.lineAt(mathEnd); for (let i = lineBegin.number; i <= lineEnd.number; i++) { const line = state.doc.line(i); decorations.push( import_view.Decoration.line({ class: "HyperMD-quote" }).range(line.from, line.from) ); const transparent = !isSourceMode && !rangesHaveOverlap(ranges, line.from, line.to); let start = 0; for (let i2 = 0; i2 < quote.level; i2++) { const index = line.text.indexOf(">", start); if (index === -1) continue; const pos = index + line.from; if (i2 === 0) { decorations.push( import_view.Decoration.mark({ class: transparent ? "cm-transparent" : "cm-quote cm-formatting-quote" }).range(pos, pos + 1) ); } else { decorations.push( import_view.Decoration.mark({ class: transparent ? "cm-blockquote-border cm-transparent" : "cm-quote cm-formatting-quote" }).range(pos, pos + 1) ); } start = index + 1; } } if (lineEnd.from < mathContentEnd && lineEnd.text.slice(0, mathContentEnd - lineEnd.from).split(">").every((s) => !s.trim())) { decorations.push( import_view.Decoration.mark({ class: "cancel-cm-math" }).range(lineEnd.from, mathContentEnd) ); } } } if (!isSourceMode && (quote == null ? void 0 : quote.isBaseCallout)) { if (overlap) { if (block) { decorations.push( import_view.Decoration.widget({ widget, block: false, side: 1 }).range(mathEnd, mathEnd) ); } } else { decorations.push( makeDeco({ widget, block: false }, mathBegin, mathEnd).range(mathBegin, mathEnd) ); } } mathBegin = -1; mathContentBegin = -1; } } } }); return import_view.Decoration.set(decorations, true); }, provide(field) { return import_view.EditorView.decorations.from(field); } }); // src/patch-widget-type.ts var import_view2 = require("@codemirror/view"); var import_view3 = require("@codemirror/view"); // node_modules/monkey-around/mjs/index.js function around(obj, factories) { const removers = Object.keys(factories).map((key) => around1(obj, key, factories[key])); return removers.length === 1 ? removers[0] : function() { removers.forEach((r) => r()); }; } function around1(obj, method, createWrapper) { const original = obj[method], hadOwn = obj.hasOwnProperty(method); let current = createWrapper(original); if (original) Object.setPrototypeOf(current, original); Object.setPrototypeOf(wrapper, current); obj[method] = wrapper; return remove; function wrapper(...args) { if (current === original && obj[method] === wrapper) remove(); return current.apply(this, args); } function remove() { if (obj[method] === wrapper) { if (hadOwn) obj[method] = original; else delete obj[method]; } if (current === original) return; current = original; Object.setPrototypeOf(wrapper, original || Function); } } // src/patch-widget-type.ts var patchDecoration = (plugin, onPatched) => { const uninstaller = around(import_view2.Decoration, { replace(old) { return function(spec) { if (!plugin.patchSucceeded && spec.widget) { plugin.patchSucceeded = patchMathWidget(plugin, spec.widget); if (plugin.patchSucceeded) { onPatched(spec.widget.constructor); uninstaller(); } } return old.call(this, spec); }; }, widget(old) { return function(spec) { if (!plugin.patchSucceeded && spec.widget) { plugin.patchSucceeded = patchMathWidget(plugin, spec.widget); if (plugin.patchSucceeded) { onPatched(spec.widget.constructor); uninstaller(); } } return old.call(this, spec); }; } }); plugin.register(uninstaller); }; function patchMathWidget(plugin, widget) { const proto = widget.constructor.prototype; const superProto = Object.getPrototypeOf(proto); const superSuperProto = Object.getPrototypeOf(superProto); const isObsidianBuiltinMathWidget = Object.hasOwn(widget, "math") && Object.hasOwn(widget, "block") && Object.hasOwn(proto, "eq") && Object.hasOwn(proto, "initDOM") && Object.hasOwn(proto, "patchDOM") && Object.hasOwn(proto, "render") && !Object.hasOwn(proto, "toDOM") && !Object.hasOwn(proto, "updateDOM") && Object.hasOwn(superProto, "become") && Object.hasOwn(superProto, "updateDOM") && Object.hasOwn(superSuperProto, "addEditButton") && Object.hasOwn(superSuperProto, "hookClickHandler") && Object.hasOwn(superSuperProto, "resizeWidget") && Object.hasOwn(superSuperProto, "setOwner") && Object.hasOwn(superSuperProto, "setPos") && Object.hasOwn(superSuperProto, "toDOM") && Object.getPrototypeOf(superSuperProto) === import_view3.WidgetType.prototype; if (isObsidianBuiltinMathWidget) { plugin.register(around(proto, { /** Newly added by this plugin: Get a quote info for the position of this math widget. */ getQuoteInfo() { return function() { return this.view ? getQuoteInfo(this.view.state, this.start - 1) : null; }; }, /** Newly added by this plugin */ markAsCorrected() { return function() { this.corrected = true; }; }, /** * Newly added by this plugin: Correct the LaTeX source code (this.math) * based on the quote info, i.e. remove an appropreate number of ">"s * at the head of each line. */ correctIfNecessary() { return function() { if (this.block && !this.corrected) { const quote = this.getQuoteInfo(); if (quote) { this.math = quote.correctMath(this.math); this.markAsCorrected(); } } }; }, eq(old) { return function(other) { if (this.block && other.block) { if (this.view && !other.view) other.view = this.view; if (other.view && !this.view) this.view = other.view; if (!this.corrected) this.correctIfNecessary(); if (!other.corrected) other.correctIfNecessary(); } return old.call(this, other); }; }, initDOM(old) { return function(view) { if (!this.view) this.view = view; return old.call(this, view); }; }, patchDOM(old) { return function(dom, view) { if (!this.view) this.view = view; return old.call(this, dom, view); }; }, render(old) { return function(dom) { this.correctIfNecessary(); old.call(this, dom); }; } })); return true; } return false; } // src/settings.ts var import_obsidian2 = require("obsidian"); var DEFAULT_SETTINGS = { notification: true }; var MathInCalloutSettingTab = class extends import_obsidian2.PluginSettingTab { constructor(plugin) { super(plugin.app, plugin); this.plugin = plugin; } display() { this.containerEl.empty(); new import_obsidian2.Setting(this.containerEl).setDesc("If something is not working, type some math expression outside callouts in Live Preview."); new import_obsidian2.Setting(this.containerEl).setName("Show setup guidance notifications").addToggle((toggle) => { toggle.setValue(this.plugin.settings.notification).onChange(async (value) => { this.plugin.settings.notification = value; await this.plugin.saveSettings(); this.plugin.showNotReadyNotice(); }); }); } }; // src/main.ts var MathInCalloutPlugin = class extends import_obsidian3.Plugin { constructor() { super(...arguments); this.notReadyNotice = null; } async onload() { await this.loadSettings(); await this.saveSettings(); this.addSettingTab(new MathInCalloutSettingTab(this)); this.patchSucceeded = false; this.registerEditorExtension(quoteInfoField); this.app.workspace.onLayoutReady(() => setTimeout(() => this.showNotReadyNotice(), 1e3)); patchDecoration(this, (builtInMathWidget) => { setTimeout(() => { if (this.notReadyNotice) { this.notReadyNotice.hide(); this.notReadyNotice = null; if (this.settings.notification) { new import_obsidian3.Notice(`${this.manifest.name}: You're ready! (Note: this notifiction can be turned off in the plugin setting.)`, 1500); } } this.registerEditorExtension(createCalloutDecorator(builtInMathWidget)); this.rerender(); }, 100); }); } rerender() { this.app.workspace.iterateAllLeaves((leaf) => { if (leaf.view instanceof import_obsidian3.MarkdownView) { const eState = leaf.view.getEphemeralState(); const editor = leaf.view.editor; editor.setValue(editor.getValue()); leaf.view.setEphemeralState(eState); } }); } showNotReadyNotice() { if (!this.patchSucceeded && this.settings.notification) { this.notReadyNotice = new import_obsidian3.Notice(`${this.manifest.name}: You're not ready yet. In Live Preview, type some math expression outside callouts.`, 0); } } async loadSettings() { this.settings = Object.assign({}, DEFAULT_SETTINGS, await this.loadData()); } async saveSettings() { await this.saveData(this.settings); } };