175 lines
5.8 KiB
TypeScript
175 lines
5.8 KiB
TypeScript
import { describe, expect, test } from "vitest";
|
|
import {
|
|
decodePageURI,
|
|
encodePageURI,
|
|
encodeRef,
|
|
isValidName,
|
|
isValidPath,
|
|
parseToRef,
|
|
} from "./ref.ts";
|
|
|
|
test("parseToRef() default cases", () => {
|
|
expect(parseToRef("foo")).toEqual({ path: "foo.md" });
|
|
expect(parseToRef("/foo")).toEqual({ path: "foo.md" });
|
|
expect(parseToRef("foo/bar")).toEqual({ path: "foo/bar.md" });
|
|
expect(parseToRef("foo.png")).toEqual({ path: "foo.png" });
|
|
expect(parseToRef("foo.md")).toEqual({ path: "foo.md" });
|
|
expect(parseToRef("foo.")).toEqual({ path: "foo..md" });
|
|
expect(parseToRef("foo..")).toEqual({ path: "foo...md" });
|
|
expect(parseToRef(" .foo")).toEqual({ path: " .foo" });
|
|
expect(parseToRef("foo[bar")).toEqual({ path: "foo[bar.md" });
|
|
expect(parseToRef("foo]bar")).toEqual({ path: "foo]bar.md" });
|
|
expect(parseToRef("foo(bar")).toEqual({ path: "foo(bar.md" });
|
|
expect(parseToRef("foo)bar")).toEqual({ path: "foo)bar.md" });
|
|
expect(parseToRef("/bar/.../foo")).toEqual({ path: "bar/.../foo.md" });
|
|
|
|
expect(parseToRef("/foo/.bar.md")).toEqual(null);
|
|
expect(parseToRef("foo.md.md")).toEqual(null);
|
|
expect(parseToRef("/.../foo")).toEqual(null);
|
|
expect(parseToRef("^.foo")).toEqual(null);
|
|
expect(parseToRef(".foobar")).toEqual(null);
|
|
expect(parseToRef("foo[[bar")).toEqual(null);
|
|
expect(parseToRef("foo]]bar")).toEqual(null);
|
|
expect(parseToRef("foo|bar")).toEqual(null);
|
|
expect(parseToRef("foo@bar")).toEqual(null);
|
|
expect(parseToRef("/../foo")).toEqual(null);
|
|
expect(parseToRef("/./foo")).toEqual(null);
|
|
expect(parseToRef("/bar/../foo")).toEqual(null);
|
|
expect(parseToRef("/bar/./foo")).toEqual(null);
|
|
|
|
expect(parseToRef("")).toEqual({ path: "" });
|
|
expect(parseToRef("/")).toEqual({ path: "" });
|
|
expect(parseToRef("/.md")).toEqual(null);
|
|
expect(parseToRef("/.foo")).toEqual(null);
|
|
expect(parseToRef("/@132")).toEqual({
|
|
path: "",
|
|
details: { type: "position", pos: 132 },
|
|
});
|
|
});
|
|
|
|
test("parseToRef() link cases", () => {
|
|
expect(parseToRef("^foo")).toEqual({ path: "foo.md", meta: true });
|
|
|
|
expect(parseToRef("foo# header")).toEqual({
|
|
path: "foo.md",
|
|
details: { type: "header", header: "header" },
|
|
});
|
|
expect(parseToRef("foo# header@123")).toEqual({
|
|
path: "foo.md",
|
|
details: { type: "header", header: "header@123" },
|
|
});
|
|
expect(parseToRef("foo@1231")).toEqual({
|
|
path: "foo.md",
|
|
details: { type: "position", pos: 1231 },
|
|
});
|
|
expect(parseToRef("foo@l42c69")).toEqual({
|
|
path: "foo.md",
|
|
details: { type: "linecolumn", line: 42, column: 69 },
|
|
});
|
|
expect(parseToRef("foo@L42C69")).toEqual({
|
|
path: "foo.md",
|
|
details: { type: "linecolumn", line: 42, column: 69 },
|
|
});
|
|
expect(parseToRef("foo@L42")).toEqual({
|
|
path: "foo.md",
|
|
details: { type: "linecolumn", line: 42, column: 1 },
|
|
});
|
|
|
|
expect(parseToRef("foo@ 123")).toEqual(null);
|
|
expect(parseToRef("foo@c69")).toEqual(null);
|
|
expect(parseToRef("foo@123#header")).toEqual(null);
|
|
expect(parseToRef("foo@123@l29")).toEqual(null);
|
|
});
|
|
|
|
test("encodeRef() cases", () => {
|
|
// Encoding
|
|
expect(encodeRef({ path: "foo.md" })).toEqual("foo");
|
|
expect(
|
|
encodeRef({ path: "foo.md", details: { type: "position", pos: 10 } }),
|
|
).toEqual("foo@10");
|
|
expect(
|
|
encodeRef({
|
|
path: "foo.md",
|
|
details: { type: "linecolumn", line: 10, column: 69 },
|
|
}),
|
|
).toEqual("foo@L10C69");
|
|
expect(
|
|
encodeRef({
|
|
path: "foo.md",
|
|
details: { type: "header", header: "bar" },
|
|
}),
|
|
).toEqual("foo#bar");
|
|
});
|
|
|
|
test("isValidPath() and isValidName()", () => {
|
|
expect(isValidPath("foo.md")).toBeTruthy();
|
|
expect(!isValidPath("foo")).toBeTruthy();
|
|
expect(!isValidPath("foo.md@123")).toBeTruthy();
|
|
|
|
expect(isValidName("foo")).toBeTruthy();
|
|
expect(!isValidName("foo.md")).toBeTruthy();
|
|
expect(!isValidName("foo@123")).toBeTruthy();
|
|
expect(!isValidName("^foo@123")).toBeTruthy();
|
|
expect(!isValidName("foo[[bar")).toBeTruthy();
|
|
|
|
// Disallow < and > in ref names
|
|
expect(!isValidName("hello<there")).toBeTruthy();
|
|
expect(!isValidName("hello>there")).toBeTruthy();
|
|
});
|
|
|
|
describe("anchor refs", () => {
|
|
test("parseToRef bare anchor", () => {
|
|
expect(parseToRef("$pete")).toEqual({
|
|
path: "",
|
|
details: { type: "anchor", name: "pete" },
|
|
});
|
|
});
|
|
|
|
test("parseToRef page-qualified anchor", () => {
|
|
expect(parseToRef("Some Page$pete")).toEqual({
|
|
path: "Some Page.md",
|
|
details: { type: "anchor", name: "pete" },
|
|
});
|
|
});
|
|
|
|
test("parseToRef accepts allowed character classes", () => {
|
|
for (const name of ["toc1", "tasks/7", "a:b", "a-b", "_foo"]) {
|
|
const ref = parseToRef("$" + name);
|
|
expect(ref?.details).toEqual({ type: "anchor", name });
|
|
}
|
|
});
|
|
|
|
test("parseToRef rejects digit-leading anchors", () => {
|
|
// "$100" should NOT be parsed as an anchor; falling through to
|
|
// the path branch should fail because the path would be "$100"
|
|
// which is not a valid path either.
|
|
expect(parseToRef("$100")).toBeNull();
|
|
});
|
|
|
|
test("encodeRef round-trips bare anchor", () => {
|
|
expect(encodeRef({ path: "", details: { type: "anchor", name: "pete" } }))
|
|
.toBe("$pete");
|
|
});
|
|
|
|
test("encodeRef round-trips page-qualified anchor", () => {
|
|
expect(
|
|
encodeRef({
|
|
path: "Some Page.md",
|
|
details: { type: "anchor", name: "pete" },
|
|
}),
|
|
).toBe("Some Page$pete");
|
|
});
|
|
});
|
|
|
|
test("Page URI encoding", () => {
|
|
expect(encodePageURI("foo")).toEqual("foo");
|
|
expect(encodePageURI("folder/foo")).toEqual("folder/foo");
|
|
expect(encodePageURI("hello there")).toEqual("hello%20there");
|
|
expect(encodePageURI("hello?there")).toEqual("hello%3Fthere");
|
|
// Now ensure all these cases are reversible
|
|
expect(decodePageURI("foo")).toEqual("foo");
|
|
expect(decodePageURI("folder/foo")).toEqual("folder/foo");
|
|
expect(decodePageURI("hello%20there")).toEqual("hello there");
|
|
expect(decodePageURI("hello%3Fthere")).toEqual("hello?there");
|
|
});
|