Recommended way to render an internal link?

Is there an API specifically for rendering internal links, something like renderInternalLink("internal link", "custom display text")? MarkdownRenderer.render() is an overkill, and I would rather not construct HTMLAnchorElement myself.

also wondering about this a lot and not been able to understand the docs… did you find the correct way to do this?

I believe there isn’t, I ended up writing my own renderer with CustomJS

class Obsidian {
    Link = class {
        /**
         * @param {TFile} file - File the link links to
         * @param {String} sourcePath - Path where the link links from
         * @param {String} displayText - Alternative display text
         */
        constructor(file, sourcePath = "", displayText) {
            this.file = file;
            this.sourcePath = sourcePath;
            this.displayText = displayText;
        }

        /**
         * Constructs a link from path, even if the target path doesn't exist.
         * Use this method for unresolved links.
         * @param {String} path - Path the link links to
         * @param {String} sourcePath - Path the link links from
         * @param {String} displayText - Alternative display text
         * @returns {Obsidian.Link}
         */
        fromPath(path, sourcePath = "", displayText) {
            this.path = path;
            this.file = app.metadataCache.getFirstLinkpathDest(path, sourcePath);
            this.sourcePath = sourcePath;
            this.displayText = displayText;
            return this;
        }

        /**
         * Construct a Link from link string
         * @param {String} string - Link string, e.g., "[[file name]]"
         * @param {String} sourcePath - Path the link links from
         * @returns {Obsidian.Link}
         */
        fromString(string, sourcePath = "") {
            const { link, display } =
                /!?\[\[(?<link>[^|\]]*)(\|(?<display>[^\]]*))?\]\]/
                .exec(string).groups;

            this.file = app.metadataCache.getFirstLinkpathDest(
                link,
                this.sourcePath
            );
            if (!this.file) {
                this.path = link;  // Unresolved link
            }
            this.sourcePath = sourcePath;
            this.displayText = display;
            this.original = string;
            return this;
        }

        /**
         * Constructs a Link from reference object
         * @param {Object} reference - Obsidian Reference object,
         *     https://docs.obsidian.md/Reference/TypeScript+API/Reference
         * @param {String} reference.displayText
         * @param {String} reference.link
         * @param {String} reference.original
         * @param {String} sourcePath - Path the link links from
         * @returns {Obsidian.Link}
         */
        fromReference(reference, sourcePath = "") {
            this.file = app.metadataCache.getFirstLinkpathDest(
                reference.link,
                this.sourcePath
            );
            if (!this.file) {
                this.path = reference.link;  // Unresolved link
            }
            this.sourcePath = sourcePath;
            this.displayText = reference.link != reference.displayText?
                reference.displayText : undefined;
            this.original = reference.original;
            return this;
        }
        
        toString() {
            let linkText = app.metadataCache.fileToLinktext(
                this.file,
                this.sourcePath
            );
            
            let displayText =
                (this.displayText == linkText)   ? undefined:
                this.displayText                 ? this.displayText:
                (this.file.basename != linkText) ? this.file.basename:
                                                   undefined;
            
            return "[["
                + linkText
                + (displayText? `|${displayText}` : '')
                + "]]";
        }

        toAnchor() {
            let linkText = this.file?
                app.metadataCache.fileToLinktext(this.file, this.sourcePath):
                this.path;  // Unresolved link
            
            let displayText = this.displayText ?? linkText;

            return createFragment().createEl("a", {
                attr: {
                    ...(this.displayText && { 'data-tooltip-position': "top" }),
                    ...(this.displayText && { 'aria-label': linkText }),
                    'data-href': linkText,
                    target: "_blank",
                    rel: "noopener"
                },
                href: linkText,
                cls: "internal-link" + (!this.file? " is-unresolved" : ""),
                text: displayText,
            });
        }

        equals(link) {
            if (this.file) {
                return this.file.path == link.file?.path;
            } else {
                return this.path
                    && this.path == link.path;  // Unresolved link
            }
        }
    }
}
2 Likes

This topic was automatically closed 28 days after the last reply. New replies are no longer allowed.