silverbullet/plug-api/lib/page_ref.ts

84 lines
2.3 KiB
TypeScript
Raw Normal View History

/**
* Possible HACK.
*
* Normally we don't want to allow pages have dots in their names,
* because we need to serve files with extensions. But there are special cases like
* "conflicted" pages. Maybe there will be some more special cases in future. This
* is why this function exists.
*
*/
export function isThisPageSpecial(name: string): boolean {
const namePatterns: RegExp[] = [
/\.conflicted\./
];
return namePatterns.some(expr => expr.test(name));
}
export function looksLikeFileName(name: string): boolean {
return /\.[a-zA-Z0-9]+$/.test(name) && !isThisPageSpecial(name)
}
export function validatePageName(name: string) {
// Page can not be empty and not end with a file extension (e.g. "bla.md")
if (name === "") {
throw new Error("Page name can not be empty");
}
if (name.startsWith(".")) {
throw new Error("Page name cannot start with a '.'");
}
if (looksLikeFileName(name)) {
throw new Error("Page name can not end with a file extension");
}
}
export type PageRef = {
page: string;
pos?: number;
anchor?: string;
2024-01-25 21:51:40 +08:00
header?: string;
};
const posRegex = /@(\d+)$/;
// Should be kept in sync with the regex in index.plug.yaml
const anchorRegex = /\$([a-zA-Z\.\-\/]+[\w\.\-\/]*)$/;
2024-01-25 21:51:40 +08:00
const headerRegex = /#([^#]*)$/;
export function parsePageRef(name: string): PageRef {
// Normalize the page name
if (name.startsWith("[[") && name.endsWith("]]")) {
name = name.slice(2, -2);
}
const pageRef: PageRef = { page: name };
const posMatch = pageRef.page.match(posRegex);
if (posMatch) {
pageRef.pos = parseInt(posMatch[1]);
pageRef.page = pageRef.page.replace(posRegex, "");
}
const anchorMatch = pageRef.page.match(anchorRegex);
if (anchorMatch) {
pageRef.anchor = anchorMatch[1];
pageRef.page = pageRef.page.replace(anchorRegex, "");
}
2024-01-25 21:51:40 +08:00
const headerMatch = pageRef.page.match(headerRegex);
if (headerMatch) {
pageRef.header = headerMatch[1];
pageRef.page = pageRef.page.replace(headerRegex, "");
}
return pageRef;
}
export function encodePageRef(pageRef: PageRef): string {
let name = pageRef.page;
if (pageRef.pos) {
name += `@${pageRef.pos}`;
}
if (pageRef.anchor) {
name += `$${pageRef.anchor}`;
}
2024-01-25 21:51:40 +08:00
if (pageRef.header) {
name += `#${pageRef.header}`;
}
return name;
}