/* 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: () => PagePropsPlugin }); module.exports = __toCommonJS(main_exports); var import_obsidian = require("obsidian"); // src/render.ts var import_view = require("@codemirror/view"); var fieldName = /([\p{L}\p{Extended_Pictographic}][0-9\p{L}\p{Extended_Pictographic}\s_/-]*)/u; function decoratedRegex(dec) { return new RegExp(`(^\\s*)${dec}${fieldName.source}${dec}(::\\s*)(.*)$`, "u"); } var regex = decoratedRegex(""); var specialRegex1 = decoratedRegex("\\*\\*"); var specialRegex2 = decoratedRegex("\\*"); var specialRegex3 = decoratedRegex("`"); var specialRegex4 = decoratedRegex("_"); function parseField(line) { let res = regex.exec(line); let extraLen = 0; if (!res) { extraLen = 4; res = specialRegex1.exec(line); if (!res) { extraLen = 2; res = specialRegex2.exec(line); if (!res) { res = specialRegex3.exec(line); if (!res) { res = specialRegex4.exec(line); if (!res) { return null; } } } } } const [, prespace, field, separator, content] = res; return { prespace, field, fieldLen: field.length + extraLen, separator, content }; } function render(plugin, field, separator, content, fieldNode) { const span = createSpan(); const text = fieldNode ? void 0 : field; const fieldEl = plugin.settings.fieldsAreInnerLinks ? createEl("a", { cls: `internal-link page-prop page-prop--${field} page-prop-field`, text, href: field, attr: { "data-href": field, spellcheck: "false", target: "_blank", rel: "noopener" }, parent: span }) : createSpan({ cls: `page-prop page-prop--${field} page-prop-field`, text, attr: { spellcheck: "false" }, parent: span }); if (fieldNode) { fieldEl.appendChild(fieldNode); } createSpan({ cls: `page-prop page-prop--${field} page-prop-separator`, text: separator, attr: { spellcheck: "false" }, parent: span }); if (content.length == 1 && content[0].nodeType == Node.TEXT_NODE) { const pattern = plugin.autolinkPatterns[field]; if (pattern) { const text2 = content[0].textContent || ""; createEl("a", { cls: `external-link page-prop page-prop--${field} page-prop-content`, text: text2, href: pattern.format(encodeURI(text2)), attr: { spellcheck: "false" }, parent: span }); return span; } } const holder = createSpan({ cls: `page-prop page-prop--${field} page-prop-content`, attr: { spellcheck: "false" }, parent: span }); for (const node of content) { holder.appendChild(node); } return span; } function createMarkdownPostProcessor(plugin) { return (el) => { if (el.childElementCount != 1) { return; } const p = el.firstChild; if (!p || p.nodeName != "P") { return; } const nodes = p.childNodes; const lines = []; let currentLine = []; for (let i = 0; i < nodes.length; i++) { const node = nodes[i]; if (node.nodeName == "BR") { lines.push(currentLine); currentLine = []; } else if (node.nodeType != Node.TEXT_NODE || node.textContent != "\n") { currentLine.push(node); } } lines.push(currentLine); for (const lineNodes of lines) { if (lineNodes.length == 0) { continue; } const [first] = lineNodes; if (first.nodeType == Node.TEXT_NODE) { const res2 = parseField(first.textContent || ""); if (!res2) { continue; } const { prespace: prespace2, field: field2, separator: separator2, content: contentTextPart } = res2; if (contentTextPart.length == 0 && lineNodes.length == 1) { continue; } if (prespace2.length != 0) { p.insertBefore(document.createTextNode(prespace2), first); } if (!plugin.settings.hideInReaderMode.contains(field2)) { const contentNodes = [document.createTextNode(contentTextPart), ...lineNodes.slice(1)]; p.insertBefore(render(plugin, field2, separator2, contentNodes), first); } p.removeChild(first); continue; } if (lineNodes.length == 1) { continue; } const [, second] = lineNodes; if (second.nodeType != Node.TEXT_NODE) { continue; } let preContent = second.textContent || ""; if (!preContent.startsWith("::")) { continue; } preContent = preContent.substring(2); const res = parseField((first.textContent || "") + "::"); if (!res) { continue; } const { prespace, field, separator } = res; if (preContent.trim().length == 0 && lineNodes.length == 2) { continue; } if (prespace.length != 0) { p.insertBefore(document.createTextNode(prespace), first); } if (!plugin.settings.hideInReaderMode.contains(field)) { const contentNodes = preContent.length != 0 ? [document.createTextNode(preContent), ...lineNodes.slice(2)] : lineNodes.slice(2); const rendered = render(plugin, field, separator, contentNodes, first); p.insertBefore(rendered, second); } p.removeChild(second); } }; } function decorate(plugin, view) { const { doc } = view.state; const widgets = []; for (const { from, to } of view.visibleRanges) { for (let i = doc.lineAt(from).number; i <= doc.lineAt(to).number; i++) { const line = doc.line(i); if (line.text.trim().length == 0) { continue; } const res = parseField(line.text); if (!res) { continue; } const { prespace, field, fieldLen, separator, content } = res; if (content.length == 0) { continue; } const nameStart = line.from + prespace.length; const nameEnd = nameStart + fieldLen; const contentStart = nameEnd + separator.length; const contentEnd = line.to; let extraClass = ""; if (plugin.settings.hideInReaderMode.contains(field)) { extraClass = " page-prop-hidden"; } if (plugin.settings.fieldsAreInnerLinks) { widgets.push(import_view.Decoration.mark({ tagName: "a", class: `internal-link page-prop${extraClass} page-prop--${field} page-prop-field`, attributes: { href: field, spellcheck: "false", draggable: "true" } }).range(nameStart, nameEnd)); } else { widgets.push(import_view.Decoration.mark({ class: `page-prop${extraClass} page-prop--${field} page-prop-field`, attributes: { spellcheck: "false" } }).range(nameStart, nameEnd)); } widgets.push(import_view.Decoration.mark({ class: `page-prop${extraClass} page-prop--${field} page-prop-separator`, attributes: { spellcheck: "false" } }).range(nameEnd, contentStart)); const cls = `page-prop${extraClass} page-prop--${field} page-prop-content`; const pattern = plugin.autolinkPatterns[field]; if (pattern) { const href = pattern.format(encodeURI(content)); widgets.push(import_view.Decoration.mark({ tagName: "a", class: `external-link page-prop page-prop--${field} page-prop-content`, attributes: { href, spellcheck: "false" } }).range(contentStart, contentEnd)); } else { widgets.push(import_view.Decoration.mark({ class: cls, attributes: { spellcheck: "false" } }).range(contentStart, contentEnd)); } } } return import_view.Decoration.set(widgets); } function createViewPlugin(plugin) { return import_view.ViewPlugin.fromClass(class { constructor(view) { this.decorations = decorate(plugin, view); } update(update) { if (update.docChanged || update.viewportChanged || update.selectionSet) { this.decorations = decorate(plugin, update.view); } } }, { decorations: (v) => v.decorations }); } // src/main.ts var DEFAULT_SETTINGS = { fieldsAreInnerLinks: true, autolinkPatterns: [ { field: "github", prefix: "https://github.com/{0}" }, { field: "wiki", prefix: "https://wikipedia.org/wiki/{0}" }, { field: "twitter", prefix: "https://twitter.com/{0}" } ], hideInReaderMode: [ "public" ] }; var PagePropsPlugin = class extends import_obsidian.Plugin { async onload() { this.settings = Object.assign({}, DEFAULT_SETTINGS, await this.loadData()); this.refreshAutolinkPatterns(); this.registerEditorExtension([createViewPlugin(this)]); this.registerMarkdownPostProcessor(createMarkdownPostProcessor(this), -100); this.addSettingTab(new Settings(this.app, this)); } refreshAutolinkPatterns() { this.autolinkPatterns = {}; for (const entry of this.settings.autolinkPatterns) { this.autolinkPatterns[entry.field] = entry.prefix; } } async saveSettings() { this.refreshAutolinkPatterns(); await this.saveData(this.settings); } }; var Settings = class extends import_obsidian.PluginSettingTab { constructor(app, plugin) { super(app, plugin); this.plugin = plugin; } display() { const { containerEl } = this; containerEl.empty(); containerEl.createEl("h2", { text: "General" }); new import_obsidian.Setting(containerEl).setName("Page property names are inner links").setDesc("A feature from Logseq, if you hover/click the page property name it'll behave as if it was a link to the page with the same name.").addToggle((toggle) => toggle.setValue(this.plugin.settings.fieldsAreInnerLinks).onChange(async (value) => { this.plugin.settings.fieldsAreInnerLinks = value; await this.plugin.saveSettings(); })); const { autolinkPatterns, hideInReaderMode } = this.plugin.settings; containerEl.createEl("h2", { text: "Fields to hide in reader view" }); for (let index = 0; index < hideInReaderMode.length; index++) { new import_obsidian.Setting(containerEl).setName("Hidden field #" + (index + 1)).addText((text) => text.setPlaceholder("Field that will be hidden").setValue(hideInReaderMode[index]).onChange(async (value) => { hideInReaderMode[index] = value; await this.plugin.saveSettings(); })).addButton((button) => button.setButtonText("-").onClick(async () => { hideInReaderMode.splice(index, 1); this.display(); await this.plugin.saveSettings(); })); } new import_obsidian.Setting(containerEl).addButton((button) => button.setWarning().setButtonText("Reset").onClick(async () => { this.plugin.settings.hideInReaderMode = [...DEFAULT_SETTINGS.hideInReaderMode]; this.display(); await this.plugin.saveSettings(); })).addButton((button) => button.setButtonText("+").onClick( async () => { hideInReaderMode.push(""); this.display(); await this.plugin.saveSettings(); } )); containerEl.createEl("h2", { text: "Autolink Patterns" }); for (let index = 0; index < autolinkPatterns.length; index++) { const entry = autolinkPatterns[index]; new import_obsidian.Setting(containerEl).setName("Pattern #" + (index + 1)).addText((text) => text.setPlaceholder("Field for the link pattern").setValue(entry.field).onChange(async (value) => { entry.field = value; await this.plugin.saveSettings(); })).addText((text) => text.setPlaceholder("The link pattern").setValue(entry.prefix).onChange(async (value) => { entry.prefix = value; await this.plugin.saveSettings(); })).addButton((button) => button.setButtonText("-").onClick(async () => { autolinkPatterns.splice(index, 1); this.display(); await this.plugin.saveSettings(); })); } new import_obsidian.Setting(containerEl).addButton((button) => button.setWarning().setButtonText("Reset").onClick(async () => { this.plugin.settings.autolinkPatterns = [...DEFAULT_SETTINGS.autolinkPatterns]; this.display(); await this.plugin.saveSettings(); })).addButton((button) => button.setButtonText("+").onClick( async () => { autolinkPatterns.push({ field: "", prefix: "" }); this.display(); await this.plugin.saveSettings(); } )); } }; /* nosourcemap */