kevboh / longform

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

Compile Step Request: Convert Wikilinks to md links for Pandoc #48

Open chrisgrieser opened 2 years ago

chrisgrieser commented 2 years ago

Right now, there is a step to remove links, but not to convert them.

This one is quite relevant for images, since the Obsidian image-wikilink syntax ![[]] does not work with Pandoc (or any other following app), which only accepts ![]().

However, this step also isn't as straightforward to implement, as the conversion would require more than just simple regexes, since for Pandoc, you have to retrieve the relative path of the image, too, a piece of info missing in the file-name-only-wikilink-syntax.

The Obsidian Link converter already does this though, so in principle, it would also be an option to make the plugin a dependency or something like that... 🤔

chrisgrieser commented 2 years ago

Could you maybe elaborate what exactly the capabilities of the longform scripts are? Can they pretty much run any javascript, similar to templater or dataview?

I just noticed this in your docs, and was wondering, whether the app as context allows you for example to run any command via app.commands.executeCommandById(""); ?

@param context The execution context of the step, including the step
    kind and option values:
      {
        app: App; // Obsidian app
      }

if the answer is yes, one could simply trigger the Link Converter's command here to streamline the whole process.

kevboh commented 2 years ago

I haven't tried running external commands in a step, but I don't see why you couldn't. In this case I would probably adapt that plugin's functionality into a dedicated step, though.

chrisgrieser commented 2 years ago

I figured out a standalone solution for the problem. again, be welcome to sherlock it :)

module.exports = {
  description: {
    name: "Convert Image Wikilinks to MD Links",
    description: "Convert Image Links to a format that can be read by third-party applications like Pandoc.",
    availableKinds: ["Manuscript"],
    options: []
  },

  // not working with scenes yet, due to https://github.com/kevboh/longform/issues/77
  compile (input, context) {
    if (!input.contents) return input;

    const imageWikiLinkRegex = /!\[\[(.*?\.(?:png|jpe?g|tiff))(?:\|(.+))?]]/g; // https://regex101.com/r/8Qzbod/1

    function linkConverter(match, p1, p2) {
        const innerWikilink = p1;
        const alias = p2 ? p2 : "";

        // convert via Obsidian API
        const linkPath = context.app.metadataCache.getFirstLinkpathDest(innerWikilink, context.projectPath).path;

        return `![${alias}](${linkPath})`;
    }
    input.contents = input.contents.replace(imageWikiLinkRegex, linkConverter);
    return input;
  }

};
chrisgrieser commented 2 years ago

Ok, thanks to the assist in #77, I managed to write it for the Manuscript and the scene level.

module.exports = {
  description: {
    name: "Convert Image Wikilinks to MD Links",
    description: "For third-party applications like Pandoc. Step must come before any 'Remove Wikilinks' step.",
    availableKinds: ["Manuscript","Scene"],
    options: []
  },

  compile (input, context) {
    const imageWikiLinkRegex = /!\[\[(.*?\.(?:png|jpe?g|tiff))(?:\|(.+))?]]/g; // https://regex101.com/r/8Qzbod/1
    function linkConverter(match, innerWikilink, alias) {
        if (!alias) alias = "";
        const linkPath = context.app.metadataCache.getFirstLinkpathDest(innerWikilink, context.projectPath).path;
        return `![${alias}](${linkPath})`;
    }
    if (context.kind === "Manuscript") {
        input.contents = input.contents.replace(imageWikiLinkRegex, linkConverter);
    }
    if (context.kind === "Scene") {
        input = input.map(i => {
            i.contents = i.contents.replace(imageWikiLinkRegex, linkConverter);
            return i;
        });
    }
    return input;
  }
};
kevboh commented 2 years ago

Nice, I plan on revisiting compile once I ship 2.0.