kevboh / longform

A plugin for Obsidian that helps you write and edit novels, screenplays, and other long projects.
Other
610 stars 30 forks source link

"Remove Links" affects certain anchor texts #260

Open Servinjesus1 opened 1 month ago

Servinjesus1 commented 1 month ago

Advanced anchor texts (i.e. figure captions) can be messed up by the current version of "Remove Links" built--in, so I wrote my own.

In particular, if you have pandoc references [@Reference] or math with vertical bars $\left|M\right|$ you may benefit from this. It essentially removes the logic to cleanse vertical bars from link anchor text, checks for newlines and skips removal if it finds a matching pair of brackets but not on one line, and skips escaped brackets.

I used ChatGPT so it also adjusted the logic which makes it hard for me to suggest a 1:1 request to update the code as it's built in.

Details

```js module.exports = { id: "remove-links", description: { name: "Remove Links", description: "Removes wiki and/or external links.", availableKinds: ["Scene", "Manuscript"], options: [ { id: "remove-wikilinks", name: "Remove Wikilinks", description: "Remove brackets from [[wikilinks]].", type: Boolean, default: true, }, { id: "remove-external-links", name: "Remove External Links", description: "Remove external links, leaving only the anchor text.", type: Boolean, default: true, }, ], }, compile(input, context) { const removeWikilinks = context.optionValues["remove-wikilinks"]; const removeExternalLinks = context.optionValues[ "remove-external-links" ]; const replaceLinks = (contents) => { if (removeWikilinks) { contents = replaceWikiLinks(contents); } if (removeExternalLinks) { contents = replaceExternalLinks(contents); } return contents; }; if (context.kind === "Scene") { return (input).map((sceneInput) => { const contents = replaceLinks(sceneInput.contents); return { ...sceneInput, contents, }; }); } else { return { ...(input), contents: replaceLinks((input).contents), }; } }, }; function replaceWikiLinks(contents) { let startOfAlias = -1; let additionalAlias = false; let end = -1; // moving backward allows us to replace within the loop, // so no additional memory. for (let i = contents.length - 1; i >= 0; i--) { const char = contents.charAt(i); if (end < 0) { if (char === "]" && i > 0 && contents.charAt(i - 1) === "]") { end = i - 1; i -= 1; } } else if (char === "|") { if (startOfAlias < 0 && !additionalAlias) { startOfAlias = i + 1; } continue; } else if (char === "[" && i > 0 && contents.charAt(i - 1) === "[") { if (i > 1 && contents.charAt(i - 2) === "!") { i -= 2; } else if (startOfAlias >= 0) { let replacement = contents.slice(startOfAlias, end); contents = contents.slice(0, i - 1) + replacement + contents.slice(end + 2); startOfAlias = -1; end = -1; additionalAlias = false; } } else if (char === "\n") { startOfAlias = -1; end = -1; additionalAlias = false; } } return contents; } function replaceExternalLinks(contents) { let end = -1; let aliasEnd = -1; let depth = 0; // moving backward allows us to replace within the loop, // so no additional memory. for (let i = contents.length - 1; i >= 0; i--) { const char = contents.charAt(i); if (end < 0) { if (char === ")") { end = i; } } else { if (aliasEnd < 0) { if (char === "(") { if (i > 0 && contents.charAt(i - 1) === "]") { aliasEnd = i - 1; } else { // invalid link end = -1; aliasEnd = -1; } // can skip the next character i = i - 1; continue; } } if (char === "]") { depth += 1; continue; } if (char === "[") { if (depth == 0) { if (i > 0 && contents.charAt(i - 1) === "!") { // embed, jump to i - 1 i -= 1; } else { const replacement = contents.slice(i + 1, aliasEnd).replace("\\", ""); contents = contents.slice(0, i) + replacement + contents.slice(end + 1); } end = -1; aliasEnd = -1; } else { depth -= 1; } continue; } } } return contents; } ```

Servinjesus1 commented 1 month ago

Edit to above code: added depth logic to count brackets. A simple workaround (escaping brackets) didn't work with pandoc-fignos, so I had to add logic that counts depth and only does replacement at zero depth (the actual caption and not inside some bracketed span in the caption) which is the better solution anyway.

Note to other pandoc users: Do not escape brackets inside captions