Files
plainleaf/plug-api/lib/transclusion.ts
T
Zef Hemel d9f4b93795 Eliminate (most) uses of the client global
Also an opportunity to refactor the transclusion code, which had become
very messy
2026-03-10 14:02:05 +01:00

112 lines
2.7 KiB
TypeScript

import {
mdLinkRegex,
wikiLinkRegex,
} from "../../client/markdown_parser/constants.ts";
import {
getNameFromPath,
parseToRef,
} from "@silverbulletmd/silverbullet/lib/ref";
export type LinkType = "wikilink" | "markdownlink";
/**
* Represents a transclusion
*/
export type Transclusion = {
url: string;
alias: string;
dimension?: ContentDimensions;
linktype: LinkType;
};
/**
* Describes the dimensions of a transclusion, if provided through the alias.
* Can be parsed from the alias using {@link parseDimensionFromAlias}
*/
export type ContentDimensions = {
width?: number;
height?: number;
};
/**
* Parse an alias, possibly containing dimensions into an object
* @example "alias", "alias|100", "alias|100x200", "100", "100x200"
*/
export function parseDimensionFromAlias(text: string): {
alias: string;
dimension?: ContentDimensions;
} {
let alias: string;
let dim: ContentDimensions | undefined;
if (text.includes("|")) {
const [aliasPart, dimPart] = text.split("|");
alias = aliasPart;
const [width, height] = dimPart.split("x");
dim = {};
if (width) {
dim.width = parseInt(width, 10);
}
if (height) {
dim.height = parseInt(height, 10);
}
} else if (/^[x\d]/.test(text)) {
const [width, height] = text.split("x");
dim = {};
if (width) {
dim.width = parseInt(width, 10);
}
if (height) {
dim.height = parseInt(height, 10);
}
alias = "";
} else {
alias = text;
}
return { alias, dimension: dim };
}
/**
* Parses a transclusion of the type `![[]]` or `![]()`
* @param text
*/
export function parseTransclusion(text: string): Transclusion | null {
let url, alias;
let linktype: LinkType = "markdownlink";
// TODO: Take in the tree and use tree nodes to get url and alias (Applies to all regex uses)
mdLinkRegex.lastIndex = 0;
wikiLinkRegex.lastIndex = 0;
let match: RegExpMatchArray | null = null;
if ((match = mdLinkRegex.exec(text)) && match.groups) {
({ url, title: alias } = match.groups);
linktype = "markdownlink";
} else if ((match = wikiLinkRegex.exec(text)) && match.groups) {
({ stringRef: url, alias } = match.groups);
linktype = "wikilink";
} else {
// We found no match
return null;
}
let dimension: ContentDimensions | undefined;
if (alias) {
({ alias, dimension: dimension } = parseDimensionFromAlias(alias));
} else {
alias = "";
}
return {
url,
alias,
dimension,
linktype,
};
}
export function nameFromTransclusion(t: Transclusion): string {
const ref = parseToRef(t.url);
if (!ref) {
throw new Error(`Cannot extract name from transclusion: ${t.url}`);
}
return getNameFromPath(ref.path);
}