371 lines
13 KiB
JavaScript
371 lines
13 KiB
JavaScript
/*
|
|
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 */ |