Integrate flowershow packages (#923)
* [packages][m]: mv @flowershow/core package here * [packages/core][xs]: rename to @portaljs/core * [package.json][xs]: setup npm workspaces * [packages/core][xs]:replace deprecated rollup executor * [core/package.json][s]: fix mermaid versions * [core/tsconfig][xs]: rm extends * [core/jest.config][xs]: rm coverageDirectory * [core/package.json][xs]: install core-js * [packages.json][s]:use same version for all nrwl packages * [core/.eslintrc][xs]: adjust ignorePatterns * [core/project.json][xs]: rm publish targets * [packages][m]: mv @flowershow/remark-wiki-link here * [packages][m]: mv @flowershow/remark-wiki-link here * [packages][m]: mv @flowershow/remark-embed here * [remark-callouts/project.json][xs]: adjst test pattern * [package.json][s]: install missing deps * [remark-callouts][xs]: adjst fields in package.json * [remark-callouts][s]: rm pubish targets and adjst build executor * [remark-embed/jest.config][xs]: rm unknown option coverageDirectory * [remark-embed][xs]: rm publish targets * [remark-embed][s]: rename to @portaljs/remark-embed * [remark-wiki-link/eslintrc][xs]:adjst ignorePatterns * [package.json][xs]: install missing deps * [remark-wiki-link/test][xs]:specify format - also temporarily force any type on htmlExtension * [remark-wiki-link/README][xs]: replace @flowershow with @portaljs * [remark-wiki-link][xs]:rm old changelog * [remark-wiki-link][xs]: adjst package.json * [remark-wiki-link/project.json][xs]: rm publish targets * [core][s]: rm old changelog * [core/README][xs]:correct scope name * [remark-callouts/README][xs]: add @portaljs to pckg name * [remark-embed/README][xs]: add @portaljs to pckg name * [package-lock.json][xs]: refresh after rebasing on main
This commit is contained in:
2
packages/remark-wiki-link/test/fixtures/content/abc.md
vendored
Normal file
2
packages/remark-wiki-link/test/fixtures/content/abc.md
vendored
Normal file
@@ -0,0 +1,2 @@
|
||||
# Document Title
|
||||
|
||||
BIN
packages/remark-wiki-link/test/fixtures/content/assets/Pasted Image 123.png
vendored
Normal file
BIN
packages/remark-wiki-link/test/fixtures/content/assets/Pasted Image 123.png
vendored
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 24 KiB |
2
packages/remark-wiki-link/test/fixtures/content/blog/Second Post.md
vendored
Normal file
2
packages/remark-wiki-link/test/fixtures/content/blog/Second Post.md
vendored
Normal file
@@ -0,0 +1,2 @@
|
||||
# Document Title
|
||||
|
||||
2
packages/remark-wiki-link/test/fixtures/content/blog/first-post.md
vendored
Normal file
2
packages/remark-wiki-link/test/fixtures/content/blog/first-post.md
vendored
Normal file
@@ -0,0 +1,2 @@
|
||||
# Document Title
|
||||
|
||||
2
packages/remark-wiki-link/test/fixtures/content/blog/index.md
vendored
Normal file
2
packages/remark-wiki-link/test/fixtures/content/blog/index.md
vendored
Normal file
@@ -0,0 +1,2 @@
|
||||
# Document Title
|
||||
|
||||
2
packages/remark-wiki-link/test/fixtures/content/blog/third-post.md
vendored
Normal file
2
packages/remark-wiki-link/test/fixtures/content/blog/third-post.md
vendored
Normal file
@@ -0,0 +1,2 @@
|
||||
# Document Title
|
||||
|
||||
2
packages/remark-wiki-link/test/fixtures/content/blog/tutorials/first-tutorial.md
vendored
Normal file
2
packages/remark-wiki-link/test/fixtures/content/blog/tutorials/first-tutorial.md
vendored
Normal file
@@ -0,0 +1,2 @@
|
||||
# Document Title
|
||||
|
||||
2
packages/remark-wiki-link/test/fixtures/content/index.md
vendored
Normal file
2
packages/remark-wiki-link/test/fixtures/content/index.md
vendored
Normal file
@@ -0,0 +1,2 @@
|
||||
# Document Title
|
||||
|
||||
62
packages/remark-wiki-link/test/getPermalinks.spec.ts
Normal file
62
packages/remark-wiki-link/test/getPermalinks.spec.ts
Normal file
@@ -0,0 +1,62 @@
|
||||
import * as path from "path";
|
||||
// import * as url from "url";
|
||||
import { getPermalinks } from "../src/utils";
|
||||
|
||||
// const __dirname = url.fileURLToPath(new URL(".", import.meta.url));
|
||||
// const markdownFolder = path.join(__dirname, "/fixtures/content");
|
||||
const markdownFolder = path.join(
|
||||
".",
|
||||
"/packages/remark-wiki-link/test/fixtures/content"
|
||||
);
|
||||
|
||||
describe("getPermalinks", () => {
|
||||
test("should return an array of permalinks", () => {
|
||||
const expectedPermalinks = [
|
||||
"/", // /index.md
|
||||
"/abc",
|
||||
"/blog/first-post",
|
||||
"/blog/Second Post",
|
||||
"/blog/third-post",
|
||||
"/blog", // /blog/index.md
|
||||
"/blog/tutorials/first-tutorial",
|
||||
"/assets/Pasted Image 123.png",
|
||||
];
|
||||
|
||||
const permalinks = getPermalinks(markdownFolder, [/\.DS_Store/]);
|
||||
expect(permalinks).toHaveLength(expectedPermalinks.length);
|
||||
permalinks.forEach((permalink) => {
|
||||
expect(expectedPermalinks).toContain(permalink);
|
||||
});
|
||||
});
|
||||
|
||||
test("should return an array of permalinks with custom path -> permalink converter function", () => {
|
||||
const expectedPermalinks = [
|
||||
"/", // /index.md
|
||||
"/abc",
|
||||
"/blog/first-post",
|
||||
"/blog/second-post",
|
||||
"/blog/third-post",
|
||||
"/blog", // /blog/index.md
|
||||
"/blog/tutorials/first-tutorial",
|
||||
"/assets/pasted-image-123.png",
|
||||
];
|
||||
|
||||
const func = (filePath: string, markdownFolder: string) => {
|
||||
const permalink = filePath
|
||||
.replace(markdownFolder, "") // make the permalink relative to the markdown folder
|
||||
.replace(/\.(mdx|md)/, "")
|
||||
.replace(/\\/g, "/") // replace windows backslash with forward slash
|
||||
.replace(/\/index$/, "") // remove index from the end of the permalink
|
||||
.replace(/ /g, "-") // replace spaces with hyphens
|
||||
.toLowerCase(); // convert to lowercase
|
||||
|
||||
return permalink.length > 0 ? permalink : "/"; // for home page
|
||||
};
|
||||
|
||||
const permalinks = getPermalinks(markdownFolder, [/\.DS_Store/], func);
|
||||
expect(permalinks).toHaveLength(expectedPermalinks.length);
|
||||
permalinks.forEach((permalink) => {
|
||||
expect(expectedPermalinks).toContain(permalink);
|
||||
});
|
||||
});
|
||||
});
|
||||
23
packages/remark-wiki-link/test/isSupportedFileFormat.spec.ts
Normal file
23
packages/remark-wiki-link/test/isSupportedFileFormat.spec.ts
Normal file
@@ -0,0 +1,23 @@
|
||||
import {
|
||||
isSupportedFileFormat,
|
||||
supportedFileFormats,
|
||||
} from "../src/lib/isSupportedFileFormat";
|
||||
|
||||
describe("isSupportedFileFormat", () => {
|
||||
test("should return [false, null] for a path with no file extension", () => {
|
||||
const filePath = "/content/some/markdown/page";
|
||||
expect(isSupportedFileFormat(filePath)).toStrictEqual([false, null]);
|
||||
});
|
||||
|
||||
test("should return [true, <extension>] for a path with supported file extension", () => {
|
||||
supportedFileFormats.forEach((fileFormat) => {
|
||||
const filePath = `image.${fileFormat}`;
|
||||
expect(isSupportedFileFormat(filePath)).toStrictEqual([true, fileFormat]);
|
||||
});
|
||||
});
|
||||
|
||||
test("should return [false, <extension>] for a path with unsupported file extension", () => {
|
||||
const filePath = "image.xyz";
|
||||
expect(isSupportedFileFormat(filePath)).toStrictEqual([false, "xyz"]);
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,312 @@
|
||||
import { syntax } from "../src/lib/syntax";
|
||||
import { html } from "../src/lib/html";
|
||||
import { micromark } from "micromark";
|
||||
|
||||
describe("micromark-extension-wiki-link", () => {
|
||||
describe("parses a wikilink", () => {
|
||||
test("with 'raw' file format (default) that has no matching permalink", () => {
|
||||
const serialized = micromark("[[Wiki Link]]", "ascii", {
|
||||
extensions: [syntax()],
|
||||
htmlExtensions: [html() as any], // TODO type fix
|
||||
});
|
||||
// note: class="internal new"
|
||||
expect(serialized).toBe(
|
||||
'<p><a href="Wiki Link" class="internal new">Wiki Link</a></p>'
|
||||
);
|
||||
});
|
||||
|
||||
test("with 'raw' file format (default) that has a matching permalink", () => {
|
||||
const serialized = micromark("[[Wiki Link]]", "ascii", {
|
||||
extensions: [syntax()],
|
||||
htmlExtensions: [html({ permalinks: ["Wiki Link"] }) as any], // TODO type fix
|
||||
});
|
||||
// note: class="internal"
|
||||
expect(serialized).toBe(
|
||||
'<p><a href="Wiki Link" class="internal">Wiki Link</a></p>'
|
||||
);
|
||||
});
|
||||
|
||||
test("with shortened Obsidian-style path that has no matching permalink", () => {
|
||||
const serialized = micromark("[[Wiki Link]]", "ascii", {
|
||||
extensions: [syntax()],
|
||||
htmlExtensions: [
|
||||
html({
|
||||
pathFormat: "obsidian-short",
|
||||
}) as any // TODO type fix
|
||||
],
|
||||
});
|
||||
// note: class="internal new"
|
||||
expect(serialized).toBe(
|
||||
'<p><a href="Wiki Link" class="internal new">Wiki Link</a></p>'
|
||||
);
|
||||
});
|
||||
|
||||
test("with shortened Obsidian-style path that has a matching permalink", () => {
|
||||
const serialized = micromark("[[Wiki Link]]", "ascii", {
|
||||
extensions: [syntax()],
|
||||
htmlExtensions: [
|
||||
html({
|
||||
permalinks: ["/some/folder/Wiki Link"],
|
||||
pathFormat: "obsidian-short",
|
||||
}) as any // TODO type fix
|
||||
],
|
||||
});
|
||||
expect(serialized).toBe(
|
||||
'<p><a href="/some/folder/Wiki Link" class="internal">Wiki Link</a></p>'
|
||||
);
|
||||
});
|
||||
|
||||
// Obsidian absolute path doesn't have a leading slash
|
||||
test("with 'obsidian-absolute' path format that has no matching permalink", () => {
|
||||
const serialized = micromark("[[some/folder/Wiki Link]]", "ascii", {
|
||||
extensions: [syntax()],
|
||||
htmlExtensions: [html({ pathFormat: "obsidian-absolute" }) as any], // TODO type fix
|
||||
});
|
||||
expect(serialized).toBe(
|
||||
'<p><a href="/some/folder/Wiki Link" class="internal new">some/folder/Wiki Link</a></p>'
|
||||
);
|
||||
});
|
||||
|
||||
// Obsidian absolute path doesn't have a leading slash
|
||||
test("with 'obsidian-absolute' path format that has a matching permalink", () => {
|
||||
const serialized = micromark("[[some/folder/Wiki Link]]", {
|
||||
extensions: [syntax()],
|
||||
htmlExtensions: [
|
||||
html({
|
||||
permalinks: ["/some/folder/Wiki Link"],
|
||||
pathFormat: "obsidian-absolute",
|
||||
}) as any // TODO type fix
|
||||
],
|
||||
});
|
||||
expect(serialized).toBe(
|
||||
'<p><a href="/some/folder/Wiki Link" class="internal">some/folder/Wiki Link</a></p>'
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
describe("aliases and headings", () => {
|
||||
test("parses a wiki link with heading", () => {
|
||||
const serialized = micromark("[[Wiki Link#Some Heading]]", "ascii", {
|
||||
extensions: [syntax()],
|
||||
htmlExtensions: [html() as any], // TODO type fix
|
||||
});
|
||||
// note: lowercased and hyphenated heading
|
||||
expect(serialized).toBe(
|
||||
'<p><a href="Wiki Link#some-heading" class="internal new">Wiki Link#Some Heading</a></p>'
|
||||
);
|
||||
});
|
||||
|
||||
test("parses a wiki link with heading and alias", () => {
|
||||
const serialized = micromark("[[Wiki Link#Some Heading|Alias]]", "ascii", {
|
||||
extensions: [syntax()],
|
||||
htmlExtensions: [html() as any], // TODO type fix
|
||||
});
|
||||
// note: lowercased and hyphenated heading
|
||||
expect(serialized).toBe(
|
||||
'<p><a href="Wiki Link#some-heading" class="internal new">Alias</a></p>'
|
||||
);
|
||||
});
|
||||
|
||||
test("parses a wiki link to a heading on the same page", () => {
|
||||
const serialized = micromark("[[#Some Heading]]", "ascii", {
|
||||
extensions: [syntax()],
|
||||
htmlExtensions: [html() as any], // TODO type fix
|
||||
});
|
||||
expect(serialized).toBe(
|
||||
'<p><a href="#some-heading" class="internal new">Some Heading</a></p>'
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
describe("image embeds", () => {
|
||||
test("parses an image embed of supported file format", () => {
|
||||
const serialized = micromark("![[My Image.jpg]]", "ascii", {
|
||||
extensions: [syntax()],
|
||||
htmlExtensions: [html() as any], // TODO type fix
|
||||
});
|
||||
expect(serialized).toBe(
|
||||
'<p><img src="My Image.jpg" alt="My Image.jpg" class="internal new" /></p>'
|
||||
);
|
||||
});
|
||||
|
||||
test("parses an image embed of unsupported file format", () => {
|
||||
const serialized = micromark("![[My Image.xyz]]", "ascii", {
|
||||
extensions: [syntax()],
|
||||
htmlExtensions: [html() as any], // TODO type fix
|
||||
});
|
||||
expect(serialized).toBe("<p>![[My Image.xyz]]</p>");
|
||||
});
|
||||
|
||||
test("parses and image ambed with a matching permalink", () => {
|
||||
const serialized = micromark("![[My Image.jpg]]", "ascii", {
|
||||
extensions: [syntax()],
|
||||
htmlExtensions: [html({ permalinks: ["My Image.jpg"] }) as any], // TODO type fix
|
||||
});
|
||||
expect(serialized).toBe(
|
||||
'<p><img src="My Image.jpg" alt="My Image.jpg" class="internal" /></p>'
|
||||
);
|
||||
});
|
||||
|
||||
test("parses an image embed with a matching permalink and Obsidian-style shortedned path", () => {
|
||||
const serialized = micromark("![[My Image.jpg]]", {
|
||||
extensions: [syntax()],
|
||||
htmlExtensions: [
|
||||
html({
|
||||
permalinks: ["/assets/My Image.jpg"],
|
||||
pathFormat: "obsidian-short",
|
||||
}) as any // TODO type fix
|
||||
],
|
||||
});
|
||||
expect(serialized).toBe(
|
||||
'<p><img src="/assets/My Image.jpg" alt="My Image.jpg" class="internal" /></p>'
|
||||
);
|
||||
});
|
||||
|
||||
test("parses an image embed with an alt text", () => {
|
||||
const serialized = micromark("![[My Image.jpg|My Image Alt]]", "ascii", {
|
||||
extensions: [syntax()],
|
||||
htmlExtensions: [html() as any], // TODO type fix
|
||||
});
|
||||
expect(serialized).toBe(
|
||||
'<p><img src="My Image.jpg" alt="My Image Alt" class="internal new" /></p>'
|
||||
);
|
||||
});
|
||||
|
||||
test("parses a pdf embed", () => {
|
||||
const serialized = micromark("![[My Document.pdf]]", "ascii", {
|
||||
extensions: [syntax()],
|
||||
htmlExtensions: [html() as any], // TODO type fix
|
||||
});
|
||||
expect(serialized).toBe(
|
||||
'<p><iframe width="100%" src="My Document.pdf#toolbar=0" class="internal new" /></p>'
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
describe("invalid wiki links", () => {
|
||||
test("doesn't parse a wiki link with two missing closing brackets", () => {
|
||||
const serialized = micromark("[[Wiki Link", "ascii", {
|
||||
extensions: [syntax()],
|
||||
htmlExtensions: [html() as any], // TODO type fix
|
||||
});
|
||||
expect(serialized).toBe("<p>[[Wiki Link</p>");
|
||||
});
|
||||
|
||||
test("doesn't parse a wiki link with one missing closing bracket", () => {
|
||||
const serialized = micromark("[[Wiki Link]", "ascii", {
|
||||
extensions: [syntax()],
|
||||
htmlExtensions: [html() as any], // TODO type fix
|
||||
});
|
||||
expect(serialized).toBe("<p>[[Wiki Link]</p>");
|
||||
});
|
||||
|
||||
test("doesn't parse a wiki link with a missing opening bracket", () => {
|
||||
const serialized = micromark("[Wiki Link]]", "ascii", {
|
||||
extensions: [syntax()],
|
||||
htmlExtensions: [html() as any], // TODO type fix
|
||||
});
|
||||
expect(serialized).toBe("<p>[Wiki Link]]</p>");
|
||||
});
|
||||
|
||||
test("doesn't parse a wiki link in single brackets", () => {
|
||||
const serialized = micromark("[Wiki Link]", "ascii", {
|
||||
extensions: [syntax()],
|
||||
htmlExtensions: [html() as any], // TODO type fix
|
||||
});
|
||||
expect(serialized).toBe("<p>[Wiki Link]</p>");
|
||||
});
|
||||
});
|
||||
|
||||
describe("other options", () => {
|
||||
test("parses a wiki link with a custom class", () => {
|
||||
const serialized = micromark("[[Wiki Link]]", "ascii", {
|
||||
extensions: [syntax()],
|
||||
htmlExtensions: [
|
||||
html({
|
||||
newClassName: "test-new",
|
||||
wikiLinkClassName: "test-wiki-link",
|
||||
}) as any // TODO type fix
|
||||
],
|
||||
});
|
||||
expect(serialized).toBe(
|
||||
'<p><a href="Wiki Link" class="test-wiki-link test-new">Wiki Link</a></p>'
|
||||
);
|
||||
});
|
||||
|
||||
test("parses a wiki link with a custom divider", () => {
|
||||
const serialized = micromark("[[Wiki Link:Alias Name]]", "ascii", {
|
||||
extensions: [syntax({ aliasDivider: ":" })],
|
||||
htmlExtensions: [html() as any], // TODO type fix
|
||||
});
|
||||
expect(serialized).toBe(
|
||||
'<p><a href="Wiki Link" class="internal new">Alias Name</a></p>'
|
||||
);
|
||||
});
|
||||
|
||||
test("parses a wiki link with a custom page resolver", () => {
|
||||
const serialized = micromark("[[Wiki Link]]", "ascii", {
|
||||
extensions: [syntax()],
|
||||
htmlExtensions: [
|
||||
html({
|
||||
wikiLinkResolver: (page) => [
|
||||
page.replace(/\s+/, "-").toLowerCase(),
|
||||
],
|
||||
}) as any // TODO type fix
|
||||
],
|
||||
});
|
||||
expect(serialized).toBe(
|
||||
'<p><a href="wiki-link" class="internal new">Wiki Link</a></p>'
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
test("parses wiki links to index files", () => {
|
||||
const serialized = micromark("[[/some/folder/index]]", "ascii", {
|
||||
extensions: [syntax()],
|
||||
htmlExtensions: [html() as any], // TODO type fix
|
||||
});
|
||||
expect(serialized).toBe(
|
||||
'<p><a href="/some/folder" class="internal new">/some/folder/index</a></p>'
|
||||
);
|
||||
});
|
||||
|
||||
describe("other", () => {
|
||||
test("parses a wiki link to some index page in a folder with no matching permalink", () => {
|
||||
const serialized = micromark("[[/some/folder/index]]", "ascii", {
|
||||
extensions: [syntax()],
|
||||
htmlExtensions: [html() as any], // TODO type fix
|
||||
});
|
||||
expect(serialized).toBe(
|
||||
'<p><a href="/some/folder" class="internal new">/some/folder/index</a></p>'
|
||||
);
|
||||
});
|
||||
|
||||
test("parses a wiki link to some index page in a folder with a matching permalink", () => {
|
||||
const serialized = micromark("[[/some/folder/index]]", "ascii", {
|
||||
extensions: [syntax()],
|
||||
htmlExtensions: [html({ permalinks: ["/some/folder"] }) as any], // TODO type fix
|
||||
});
|
||||
expect(serialized).toBe(
|
||||
'<p><a href="/some/folder" class="internal">/some/folder/index</a></p>'
|
||||
);
|
||||
});
|
||||
|
||||
test("parses a wiki link to home index page with no matching permalink", () => {
|
||||
const serialized = micromark("[[/index]]", "ascii", {
|
||||
extensions: [syntax()],
|
||||
htmlExtensions: [html() as any], // TODO type fix
|
||||
});
|
||||
expect(serialized).toBe(
|
||||
'<p><a href="/" class="internal new">/index</a></p>'
|
||||
);
|
||||
});
|
||||
|
||||
test("parses a wiki link to home index page with a matching permalink", () => {
|
||||
const serialized = micromark("[[/index]]", "ascii", {
|
||||
extensions: [syntax()],
|
||||
htmlExtensions: [html({ permalinks: ["/"] }) as any], // TODO type fix
|
||||
});
|
||||
expect(serialized).toBe('<p><a href="/" class="internal">/index</a></p>');
|
||||
});
|
||||
});
|
||||
});
|
||||
538
packages/remark-wiki-link/test/remarkWikiLink.spec.ts
Normal file
538
packages/remark-wiki-link/test/remarkWikiLink.spec.ts
Normal file
@@ -0,0 +1,538 @@
|
||||
import markdown from "remark-parse";
|
||||
import { unified } from "unified";
|
||||
import { select } from "unist-util-select";
|
||||
import { visit } from "unist-util-visit";
|
||||
import { Node } from "unist";
|
||||
|
||||
import wikiLinkPlugin from "../src/lib/remarkWikiLink";
|
||||
|
||||
describe("remark-wiki-link", () => {
|
||||
describe("parses a wikilink", () => {
|
||||
test("with 'raw' file format (default) that has no matching permalink", () => {
|
||||
const processor = unified().use(markdown).use(wikiLinkPlugin);
|
||||
|
||||
let ast = processor.parse("[[Wiki Link]]");
|
||||
ast = processor.runSync(ast);
|
||||
|
||||
expect(select("wikiLink", ast)).not.toEqual(null);
|
||||
|
||||
visit(ast, "wikiLink", (node: Node) => {
|
||||
expect(node.data?.exists).toEqual(false);
|
||||
expect(node.data?.permalink).toEqual("Wiki Link");
|
||||
expect(node.data?.alias).toEqual(null);
|
||||
expect(node.data?.hName).toEqual("a");
|
||||
expect((node.data?.hProperties as any).className).toEqual(
|
||||
"internal new"
|
||||
);
|
||||
expect((node.data?.hProperties as any).href).toEqual("Wiki Link");
|
||||
expect((node.data?.hChildren as any)[0].value).toEqual("Wiki Link");
|
||||
});
|
||||
});
|
||||
|
||||
test("with 'raw' file format (default) that has a matching permalink", () => {
|
||||
const processor = unified()
|
||||
.use(markdown)
|
||||
.use(wikiLinkPlugin, {
|
||||
permalinks: ["Wiki Link"],
|
||||
});
|
||||
|
||||
let ast = processor.parse("[[Wiki Link]]");
|
||||
ast = processor.runSync(ast);
|
||||
|
||||
expect(select("wikiLink", ast)).not.toEqual(null);
|
||||
|
||||
visit(ast, "wikiLink", (node: Node) => {
|
||||
expect(node.data?.exists).toEqual(true);
|
||||
expect(node.data?.permalink).toEqual("Wiki Link");
|
||||
expect(node.data?.alias).toEqual(null);
|
||||
expect(node.data?.hName).toEqual("a");
|
||||
expect((node.data?.hProperties as any).className).toEqual("internal");
|
||||
expect((node.data?.hProperties as any).href).toEqual("Wiki Link");
|
||||
expect((node.data?.hChildren as any)[0].value).toEqual("Wiki Link");
|
||||
});
|
||||
});
|
||||
|
||||
test("with shortened Obsidian-style path that has no matching permalink", () => {
|
||||
const processor = unified().use(markdown).use(wikiLinkPlugin, {
|
||||
pathFormat: "obsidian-short",
|
||||
});
|
||||
|
||||
let ast = processor.parse("[[Wiki Link]]");
|
||||
ast = processor.runSync(ast);
|
||||
|
||||
expect(select("wikiLink", ast)).not.toEqual(null);
|
||||
|
||||
visit(ast, "wikiLink", (node: Node) => {
|
||||
expect(node.data?.exists).toEqual(false);
|
||||
expect(node.data?.permalink).toEqual("Wiki Link");
|
||||
expect(node.data?.alias).toEqual(null);
|
||||
expect(node.data?.hName).toEqual("a");
|
||||
expect((node.data?.hProperties as any).className).toEqual(
|
||||
"internal new"
|
||||
);
|
||||
expect((node.data?.hProperties as any).href).toEqual("Wiki Link");
|
||||
expect((node.data?.hChildren as any)[0].value).toEqual("Wiki Link");
|
||||
});
|
||||
});
|
||||
|
||||
test("with shortened Obsidian-style path that has a matching permalink", () => {
|
||||
const processor = unified()
|
||||
.use(markdown)
|
||||
.use(wikiLinkPlugin, {
|
||||
permalinks: ["/some/folder/Wiki Link"],
|
||||
pathFormat: "obsidian-short",
|
||||
});
|
||||
|
||||
let ast = processor.parse("[[Wiki Link]]");
|
||||
ast = processor.runSync(ast);
|
||||
|
||||
expect(select("wikiLink", ast)).not.toEqual(null);
|
||||
|
||||
visit(ast, "wikiLink", (node: Node) => {
|
||||
expect(node.data?.exists).toEqual(true);
|
||||
expect(node.data?.permalink).toEqual("/some/folder/Wiki Link");
|
||||
expect(node.data?.alias).toEqual(null);
|
||||
expect(node.data?.hName).toEqual("a");
|
||||
expect((node.data?.hProperties as any).className).toEqual("internal");
|
||||
expect((node.data?.hProperties as any).href).toEqual(
|
||||
"/some/folder/Wiki Link"
|
||||
);
|
||||
expect((node.data?.hChildren as any)[0].value).toEqual("Wiki Link");
|
||||
});
|
||||
});
|
||||
|
||||
// Obsidian absolute path doesn't have a leading slash
|
||||
test("with 'obsidian-absolute' path format that has no matching permalink", () => {
|
||||
const processor = unified()
|
||||
.use(markdown)
|
||||
.use(wikiLinkPlugin, { pathFormat: "obsidian-absolute" });
|
||||
|
||||
let ast = processor.parse("[[some/folder/Wiki Link]]");
|
||||
ast = processor.runSync(ast);
|
||||
|
||||
expect(select("wikiLink", ast)).not.toEqual(null);
|
||||
|
||||
visit(ast, "wikiLink", (node: Node) => {
|
||||
expect(node.data?.exists).toEqual(false);
|
||||
expect(node.data?.permalink).toEqual("/some/folder/Wiki Link");
|
||||
expect(node.data?.alias).toEqual(null);
|
||||
expect(node.data?.hName).toEqual("a");
|
||||
expect((node.data?.hProperties as any).className).toEqual(
|
||||
"internal new"
|
||||
);
|
||||
expect((node.data?.hProperties as any).href).toEqual(
|
||||
"/some/folder/Wiki Link"
|
||||
);
|
||||
expect((node.data?.hChildren as any)[0].value).toEqual(
|
||||
"some/folder/Wiki Link"
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
// Obsidian absolute path doesn't have a leading slash
|
||||
test("with 'obsidian-absolute' path format that has a matching permalink", () => {
|
||||
const processor = unified()
|
||||
.use(markdown)
|
||||
.use(wikiLinkPlugin, {
|
||||
permalinks: ["/some/folder/Wiki Link"],
|
||||
pathFormat: "obsidian-absolute",
|
||||
});
|
||||
|
||||
let ast = processor.parse("[[some/folder/Wiki Link]]");
|
||||
ast = processor.runSync(ast);
|
||||
|
||||
expect(select("wikiLink", ast)).not.toEqual(null);
|
||||
|
||||
visit(ast, "wikiLink", (node: Node) => {
|
||||
expect(node.data?.exists).toEqual(true);
|
||||
expect(node.data?.permalink).toEqual("/some/folder/Wiki Link");
|
||||
expect(node.data?.alias).toEqual(null);
|
||||
expect(node.data?.hName).toEqual("a");
|
||||
expect((node.data?.hProperties as any).className).toEqual("internal");
|
||||
expect((node.data?.hProperties as any).href).toEqual(
|
||||
"/some/folder/Wiki Link"
|
||||
);
|
||||
expect((node.data?.hChildren as any)[0].value).toEqual(
|
||||
"some/folder/Wiki Link"
|
||||
);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe("aliases and headings", () => {
|
||||
test("parses a wiki link with heading", () => {
|
||||
const processor = unified().use(markdown).use(wikiLinkPlugin);
|
||||
|
||||
let ast = processor.parse("[[Wiki Link#Some Heading]]");
|
||||
ast = processor.runSync(ast);
|
||||
|
||||
expect(select("wikiLink", ast)).not.toEqual(null);
|
||||
|
||||
visit(ast, "wikiLink", (node: Node) => {
|
||||
expect(node.data?.exists).toEqual(false);
|
||||
expect(node.data?.permalink).toEqual("Wiki Link");
|
||||
expect(node.data?.alias).toEqual(null);
|
||||
expect(node.data?.hName).toEqual("a");
|
||||
expect((node.data?.hProperties as any).className).toEqual(
|
||||
"internal new"
|
||||
);
|
||||
expect((node.data?.hProperties as any).href).toEqual(
|
||||
"Wiki Link#some-heading"
|
||||
);
|
||||
expect((node.data?.hChildren as any)[0].value).toEqual(
|
||||
"Wiki Link#Some Heading"
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
test("parses a wiki link with heading and alias", () => {
|
||||
const processor = unified().use(markdown).use(wikiLinkPlugin);
|
||||
|
||||
let ast = processor.parse("[[Wiki Link#Some Heading|Alias]]");
|
||||
ast = processor.runSync(ast);
|
||||
|
||||
expect(select("wikiLink", ast)).not.toEqual(null);
|
||||
|
||||
visit(ast, "wikiLink", (node: Node) => {
|
||||
expect(node.data?.exists).toEqual(false);
|
||||
expect(node.data?.permalink).toEqual("Wiki Link");
|
||||
expect(node.data?.alias).toEqual("Alias");
|
||||
expect(node.data?.hName).toEqual("a");
|
||||
expect((node.data?.hProperties as any).className).toEqual(
|
||||
"internal new"
|
||||
);
|
||||
expect((node.data?.hProperties as any).href).toEqual(
|
||||
"Wiki Link#some-heading"
|
||||
);
|
||||
expect((node.data?.hChildren as any)[0].value).toEqual("Alias");
|
||||
});
|
||||
});
|
||||
|
||||
test("parses a wiki link to a heading on the same page", () => {
|
||||
const processor = unified().use(markdown).use(wikiLinkPlugin);
|
||||
|
||||
let ast = processor.parse("[[#Some Heading]]");
|
||||
ast = processor.runSync(ast);
|
||||
|
||||
expect(select("wikiLink", ast)).not.toEqual(null);
|
||||
|
||||
visit(ast, "wikiLink", (node: Node) => {
|
||||
expect(node.data?.exists).toEqual(false);
|
||||
expect(node.data?.permalink).toEqual(""); // TODO should this be null?
|
||||
expect(node.data?.alias).toEqual(null);
|
||||
expect(node.data?.hName).toEqual("a");
|
||||
expect((node.data?.hProperties as any).className).toEqual(
|
||||
"internal new"
|
||||
);
|
||||
expect((node.data?.hProperties as any).href).toEqual("#some-heading");
|
||||
expect((node.data?.hChildren as any)[0].value).toEqual("Some Heading");
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe("image embeds", () => {
|
||||
test("parses an image embed of supported file format", () => {
|
||||
const processor = unified().use(markdown).use(wikiLinkPlugin);
|
||||
|
||||
let ast = processor.parse("![[My Image.png]]");
|
||||
ast = processor.runSync(ast);
|
||||
|
||||
expect(select("wikiLink", ast)).not.toEqual(null);
|
||||
|
||||
visit(ast, "wikiLink", (node: Node) => {
|
||||
expect(node.data?.isEmbed).toEqual(true);
|
||||
expect(node.data?.target).toEqual("My Image.png");
|
||||
expect(node.data?.permalink).toEqual("My Image.png");
|
||||
expect(node.data?.hName).toEqual("img");
|
||||
expect((node.data?.hProperties as any).src).toEqual("My Image.png");
|
||||
expect((node.data?.hProperties as any).alt).toEqual("My Image.png");
|
||||
});
|
||||
});
|
||||
|
||||
test("parses an image embed of unsupported file format", () => {
|
||||
const processor = unified().use(markdown).use(wikiLinkPlugin);
|
||||
|
||||
let ast = processor.parse("![[My Image.xyz]]");
|
||||
ast = processor.runSync(ast);
|
||||
|
||||
expect(select("wikiLink", ast)).not.toEqual(null);
|
||||
|
||||
visit(ast, "wikiLink", (node: Node) => {
|
||||
expect(node.data?.isEmbed).toEqual(true);
|
||||
expect(node.data?.target).toEqual("My Image.xyz");
|
||||
expect(node.data?.permalink).toEqual("My Image.xyz");
|
||||
expect(node.data?.hName).toEqual("p");
|
||||
expect((node.data?.hChildren as any)[0].value).toEqual(
|
||||
"![[My Image.xyz]]"
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
test("parses an image embed with a matching permalink", () => {
|
||||
const processor = unified()
|
||||
.use(markdown)
|
||||
.use(wikiLinkPlugin, {
|
||||
permalinks: ["Pasted Image 123.png"],
|
||||
});
|
||||
|
||||
let ast = processor.parse("![[Pasted Image 123.png]]");
|
||||
ast = processor.runSync(ast);
|
||||
|
||||
expect(select("wikiLink", ast)).not.toEqual(null);
|
||||
|
||||
visit(ast, "wikiLink", (node: Node) => {
|
||||
expect(node.data?.isEmbed).toEqual(true);
|
||||
expect(node.data?.target).toEqual("Pasted Image 123.png");
|
||||
expect(node.data?.exists).toEqual(true);
|
||||
expect(node.data?.permalink).toEqual("Pasted Image 123.png");
|
||||
expect(node.data?.hName).toEqual("img");
|
||||
expect((node.data?.hProperties as any).src).toEqual(
|
||||
"Pasted Image 123.png"
|
||||
);
|
||||
expect((node.data?.hProperties as any).alt).toEqual(
|
||||
"Pasted Image 123.png"
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
test("parses an image embed with a matching permalink and Obsidian-style shortedned path", () => {
|
||||
const processor = unified()
|
||||
.use(markdown)
|
||||
.use(wikiLinkPlugin, {
|
||||
pathFormat: "obsidian-short",
|
||||
permalinks: ["/assets/Pasted Image 123.png"],
|
||||
});
|
||||
|
||||
let ast = processor.parse("![[Pasted Image 123.png]]");
|
||||
ast = processor.runSync(ast);
|
||||
|
||||
expect(select("wikiLink", ast)).not.toEqual(null);
|
||||
|
||||
visit(ast, "wikiLink", (node: Node) => {
|
||||
expect(node.data?.isEmbed).toEqual(true);
|
||||
expect(node.data?.target).toEqual("Pasted Image 123.png");
|
||||
expect(node.data?.exists).toEqual(true);
|
||||
expect(node.data?.permalink).toEqual("/assets/Pasted Image 123.png");
|
||||
expect(node.data?.hName).toEqual("img");
|
||||
expect((node.data?.hProperties as any).src).toEqual(
|
||||
"/assets/Pasted Image 123.png"
|
||||
);
|
||||
expect((node.data?.hProperties as any).alt).toEqual(
|
||||
"Pasted Image 123.png"
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
test("parses an image embed with an alt text", () => {
|
||||
const processor = unified().use(markdown).use(wikiLinkPlugin);
|
||||
|
||||
let ast = processor.parse("![[My Image.png|Alt Text]]");
|
||||
ast = processor.runSync(ast);
|
||||
|
||||
expect(select("wikiLink", ast)).not.toEqual(null);
|
||||
|
||||
visit(ast, "wikiLink", (node: Node) => {
|
||||
expect(node.data?.isEmbed).toEqual(true);
|
||||
expect(node.data?.target).toEqual("My Image.png");
|
||||
expect(node.data?.permalink).toEqual("My Image.png");
|
||||
expect(node.data?.hName).toEqual("img");
|
||||
expect((node.data?.hProperties as any).src).toEqual("My Image.png");
|
||||
expect((node.data?.hProperties as any).alt).toEqual("Alt Text");
|
||||
});
|
||||
});
|
||||
|
||||
test("parses a pdf embed", () => {
|
||||
const processor = unified().use(markdown).use(wikiLinkPlugin);
|
||||
|
||||
let ast = processor.parse("![[My Document.pdf]]");
|
||||
ast = processor.runSync(ast);
|
||||
|
||||
expect(select("wikiLink", ast)).not.toEqual(null);
|
||||
|
||||
visit(ast, "wikiLink", (node: Node) => {
|
||||
expect(node.data?.isEmbed).toEqual(true);
|
||||
expect(node.data?.target).toEqual("My Document.pdf");
|
||||
expect(node.data?.permalink).toEqual("My Document.pdf");
|
||||
expect(node.data?.hName).toEqual("iframe");
|
||||
expect((node.data?.hProperties as any).src).toEqual(
|
||||
"My Document.pdf#toolbar=0"
|
||||
);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe("invalid wiki links", () => {
|
||||
test("doesn't parse a wiki link with two missing closing brackets", () => {
|
||||
const processor = unified().use(markdown).use(wikiLinkPlugin);
|
||||
|
||||
let ast = processor.parse("[[Wiki Link");
|
||||
ast = processor.runSync(ast);
|
||||
|
||||
expect(select("wikiLink", ast)).toEqual(null);
|
||||
});
|
||||
|
||||
test("doesn't parse a wiki link with one missing closing bracket", () => {
|
||||
const processor = unified().use(markdown).use(wikiLinkPlugin);
|
||||
|
||||
let ast = processor.parse("[[Wiki Link]");
|
||||
ast = processor.runSync(ast);
|
||||
|
||||
expect(select("wikiLink", ast)).toEqual(null);
|
||||
});
|
||||
|
||||
test("doesn't parse a wiki link with a missing opening bracket", () => {
|
||||
const processor = unified().use(markdown).use(wikiLinkPlugin);
|
||||
|
||||
let ast = processor.parse("Wiki Link]]");
|
||||
ast = processor.runSync(ast);
|
||||
|
||||
expect(select("wikiLink", ast)).toEqual(null);
|
||||
});
|
||||
|
||||
test("doesn't parse a wiki link in single brackets", () => {
|
||||
const processor = unified().use(markdown).use(wikiLinkPlugin);
|
||||
|
||||
let ast = processor.parse("[Wiki Link]");
|
||||
ast = processor.runSync(ast);
|
||||
|
||||
expect(select("wikiLink", ast)).toEqual(null);
|
||||
});
|
||||
});
|
||||
|
||||
test("supports different config options", () => {
|
||||
const processor = unified()
|
||||
.use(markdown)
|
||||
.use(wikiLinkPlugin, {
|
||||
aliasDivider: ":",
|
||||
pathFormat: "obsidian-short",
|
||||
permalinks: ["/some/folder/123/real-page"],
|
||||
wikiLinkResolver: (pageName: string) => [
|
||||
`123/${pageName.replace(/ /g, "-").toLowerCase()}`,
|
||||
],
|
||||
wikiLinkClassName: "my-wiki-link-class",
|
||||
hrefTemplate: (permalink: string) => `https://my-site.com${permalink}`,
|
||||
});
|
||||
|
||||
let ast = processor.parse("[[Real Page#Some Heading:Page Alias]]");
|
||||
ast = processor.runSync(ast);
|
||||
|
||||
expect(select("wikiLink", ast)).not.toEqual(null);
|
||||
|
||||
visit(ast, "wikiLink", (node: Node) => {
|
||||
expect(node.data?.exists).toEqual(true);
|
||||
expect(node.data?.permalink).toEqual("/some/folder/123/real-page");
|
||||
expect(node.data?.alias).toEqual("Page Alias");
|
||||
expect(node.data?.hName).toEqual("a");
|
||||
expect((node.data?.hProperties as any).className).toEqual(
|
||||
"my-wiki-link-class"
|
||||
);
|
||||
expect((node.data?.hProperties as any).href).toEqual(
|
||||
"https://my-site.com/some/folder/123/real-page#some-heading"
|
||||
);
|
||||
expect((node.data?.hChildren as any)[0].value).toEqual("Page Alias");
|
||||
});
|
||||
});
|
||||
|
||||
test("parses wiki links to index files", () => {
|
||||
const processor = unified().use(markdown).use(wikiLinkPlugin);
|
||||
|
||||
let ast = processor.parse("[[/some/folder/index]]");
|
||||
ast = processor.runSync(ast);
|
||||
|
||||
expect(select("wikiLink", ast)).not.toEqual(null);
|
||||
|
||||
visit(ast, "wikiLink", (node: Node) => {
|
||||
expect(node.data?.exists).toEqual(false);
|
||||
expect(node.data?.permalink).toEqual("/some/folder");
|
||||
expect(node.data?.alias).toEqual(null);
|
||||
expect(node.data?.hName).toEqual("a");
|
||||
expect((node.data?.hProperties as any).className).toEqual("internal new");
|
||||
expect((node.data?.hProperties as any).href).toEqual("/some/folder");
|
||||
expect((node.data?.hChildren as any)[0].value).toEqual(
|
||||
"/some/folder/index"
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
describe("other", () => {
|
||||
test("parses a wiki link to some index page in a folder with no matching permalink", () => {
|
||||
const processor = unified().use(markdown).use(wikiLinkPlugin);
|
||||
|
||||
let ast = processor.parse("[[/some/folder/index]]");
|
||||
ast = processor.runSync(ast);
|
||||
|
||||
visit(ast, "wikiLink", (node: Node) => {
|
||||
expect(node.data?.exists).toEqual(false);
|
||||
expect(node.data?.permalink).toEqual("/some/folder");
|
||||
expect(node.data?.alias).toEqual(null);
|
||||
expect(node.data?.hName).toEqual("a");
|
||||
expect((node.data?.hProperties as any).className).toEqual(
|
||||
"internal new"
|
||||
);
|
||||
expect((node.data?.hProperties as any).href).toEqual("/some/folder");
|
||||
expect((node.data?.hChildren as any)[0].value).toEqual(
|
||||
"/some/folder/index"
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
test("parses a wiki link to some index page in a folder with a matching permalink", () => {
|
||||
const processor = unified()
|
||||
.use(markdown)
|
||||
.use(wikiLinkPlugin, { permalinks: ["/some/folder"] });
|
||||
|
||||
let ast = processor.parse("[[/some/folder/index]]");
|
||||
ast = processor.runSync(ast);
|
||||
|
||||
visit(ast, "wikiLink", (node: Node) => {
|
||||
expect(node.data?.exists).toEqual(true);
|
||||
expect(node.data?.permalink).toEqual("/some/folder");
|
||||
expect(node.data?.alias).toEqual(null);
|
||||
expect(node.data?.hName).toEqual("a");
|
||||
expect((node.data?.hProperties as any).className).toEqual("internal");
|
||||
expect((node.data?.hProperties as any).href).toEqual("/some/folder");
|
||||
expect((node.data?.hChildren as any)[0].value).toEqual(
|
||||
"/some/folder/index"
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
test("parses a wiki link to home index page with no matching permalink", () => {
|
||||
const processor = unified().use(markdown).use(wikiLinkPlugin);
|
||||
|
||||
let ast = processor.parse("[[/index]]");
|
||||
ast = processor.runSync(ast);
|
||||
|
||||
visit(ast, "wikiLink", (node: Node) => {
|
||||
expect(node.data?.exists).toEqual(false);
|
||||
expect(node.data?.permalink).toEqual("/");
|
||||
expect(node.data?.alias).toEqual(null);
|
||||
expect(node.data?.hName).toEqual("a");
|
||||
expect((node.data?.hProperties as any).className).toEqual(
|
||||
"internal new"
|
||||
);
|
||||
expect((node.data?.hProperties as any).href).toEqual("/");
|
||||
expect((node.data?.hChildren as any)[0].value).toEqual("/index");
|
||||
});
|
||||
});
|
||||
|
||||
test("parses a wiki link to home index page with a matching permalink", () => {
|
||||
const processor = unified()
|
||||
.use(markdown)
|
||||
.use(wikiLinkPlugin, { permalinks: ["/"] });
|
||||
|
||||
let ast = processor.parse("[[/index]]");
|
||||
ast = processor.runSync(ast);
|
||||
|
||||
visit(ast, "wikiLink", (node: Node) => {
|
||||
expect(node.data?.exists).toEqual(true);
|
||||
expect(node.data?.permalink).toEqual("/");
|
||||
expect(node.data?.alias).toEqual(null);
|
||||
expect(node.data?.hName).toEqual("a");
|
||||
expect((node.data?.hProperties as any).className).toEqual("internal");
|
||||
expect((node.data?.hProperties as any).href).toEqual("/");
|
||||
expect((node.data?.hChildren as any)[0].value).toEqual("/index");
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user