Skip to content

Commit

Permalink
feat(markdown): create markdown package
Browse files Browse the repository at this point in the history
  • Loading branch information
sdorra committed Mar 30, 2024
1 parent 25ec588 commit 2ba1bac
Show file tree
Hide file tree
Showing 32 changed files with 1,088 additions and 41 deletions.
4 changes: 4 additions & 0 deletions .better-commits.json
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,10 @@
"value": "mdx",
"label": "mdx"
},
{
"value": "markdown",
"label": "markdown"
},
{
"value": "shared",
"label": "shared"
Expand Down
1 change: 1 addition & 0 deletions .commitlintrc.json
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
"next",
"solid-start",
"mdx",
"markdown",
"shared"
]
]
Expand Down
2 changes: 1 addition & 1 deletion integrations/solid/characters/arthur.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,4 +5,4 @@ species: Human
source: https://hitchhikers.fandom.com/wiki/Arthur_Dent
---

Arthur Dent is a friendly but simple-minded human from Earth who escaped his planet's destruction and travelled the universe with his best friend, Ford Prefect. He spent several years being helplessly launched from crisis to crisis while trying to straighten out his lifestyle.
**Arthur Dent** is a friendly but simple-minded human from Earth who escaped his planet's destruction and travelled the universe with his best friend, **Ford Prefect**. He spent several years being helplessly launched from crisis to crisis while trying to straighten out his lifestyle.
2 changes: 1 addition & 1 deletion integrations/solid/characters/ford.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,4 +5,4 @@ species: Betelgeusian
source: https://hitchhikers.fandom.com/wiki/Ford_Prefect
---

Ford Prefect is an adventurous, eccentric, and existentialist Betelgeusian field researcher for The Hitchhiker's Guide to the Galaxy who traveled across the universe with Arthur Dent on many bizarre adventures, primarily as a crewman on the Heart of Gold and the Bistromath.
**Ford Prefect** is an adventurous, eccentric, and existentialist Betelgeusian field researcher for The Hitchhiker's Guide to the Galaxy who traveled across the universe with Arthur Dent on many bizarre adventures, primarily as a crewman on the Heart of Gold and the Bistromath.
8 changes: 8 additions & 0 deletions integrations/solid/content-collections.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { defineCollection, defineConfig } from "@content-collections/core";
import { compileMarkdown } from "@content-collections/markdown"

const characters = defineCollection({
name: "characters",
Expand All @@ -10,6 +11,13 @@ const characters = defineCollection({
species: z.string().min(1),
source: z.string().min(1).url(),
}),
transform: async (document, context) => {
const content = await compileMarkdown(context, document);
return {
...document,
content,
};
}
});

export default defineConfig({
Expand Down
1 change: 1 addition & 0 deletions integrations/solid/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
},
"dependencies": {
"@content-collections/core": "0.4.0",
"@content-collections/markdown": "0.1.0",
"@content-collections/solid-start": "0.1.1",
"@playwright/test": "^1.42.1",
"@solidjs/start": "^1.0.0-rc.0",
Expand Down
2 changes: 1 addition & 1 deletion integrations/solid/src/app.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ export default function App() {
{allCharacters.map((character) => (
<li>
<h2>{character.name}</h2>
<p>{character.content}</p>
<div innerHTML={character.content} />
</li>
))}
</ul>
Expand Down
2 changes: 1 addition & 1 deletion integrations/svelte-kit/characters/arthur.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,4 +5,4 @@ species: Human
source: https://hitchhikers.fandom.com/wiki/Arthur_Dent
---

Arthur Dent is a friendly but simple-minded human from Earth who escaped his planet's destruction and travelled the universe with his best friend, Ford Prefect. He spent several years being helplessly launched from crisis to crisis while trying to straighten out his lifestyle.
**Arthur Dent** is a friendly but simple-minded human from Earth who escaped his planet's destruction and travelled the universe with his best friend, **Ford Prefect**. He spent several years being helplessly launched from crisis to crisis while trying to straighten out his lifestyle.
2 changes: 1 addition & 1 deletion integrations/svelte-kit/characters/ford.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,4 +5,4 @@ species: Betelgeusian
source: https://hitchhikers.fandom.com/wiki/Ford_Prefect
---

Ford Prefect is an adventurous, eccentric, and existentialist Betelgeusian field researcher for The Hitchhiker's Guide to the Galaxy who traveled across the universe with Arthur Dent on many bizarre adventures, primarily as a crewman on the Heart of Gold and the Bistromath.
**Ford Prefect** is an adventurous, eccentric, and existentialist Betelgeusian field researcher for The Hitchhiker's Guide to the Galaxy who traveled across the universe with Arthur Dent on many bizarre adventures, primarily as a crewman on the Heart of Gold and the Bistromath.
8 changes: 8 additions & 0 deletions integrations/svelte-kit/content-collections.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { defineCollection, defineConfig } from "@content-collections/core";
import { compileMarkdown } from "@content-collections/markdown";

const characters = defineCollection({
name: "characters",
Expand All @@ -10,6 +11,13 @@ const characters = defineCollection({
species: z.string().min(1),
source: z.string().min(1).url(),
}),
transform: async (document, context) => {
const content = await compileMarkdown(context, document);
return {
...document,
content,
};
},
});

export default defineConfig({
Expand Down
1 change: 1 addition & 0 deletions integrations/svelte-kit/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
},
"devDependencies": {
"@content-collections/core": "0.4.0",
"@content-collections/markdown": "0.1.0",
"@content-collections/vite": "0.2.1",
"@playwright/test": "^1.42.1",
"@sveltejs/adapter-auto": "^3.0.0",
Expand Down
2 changes: 1 addition & 1 deletion integrations/svelte-kit/src/routes/+page.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
{#each allCharacters as character}
<li>
<h2>{character.name}</h2>
<p>{character.content}</p>
<div>{@html character.content}</div>
</li>
{/each}
</ul>
38 changes: 38 additions & 0 deletions packages/markdown/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
{
"name": "@content-collections/markdown",
"description": "Compile markdown to html as part of your content-collection transform function",
"version": "0.1.0",
"type": "module",
"main": "dist/index.js",
"types": "./dist/index.d.ts",
"exports": {
"./package.json": "./package.json",
".": {
"import": "./dist/index.js",
"types": "./dist/index.d.ts"
}
},
"scripts": {
"build": "tsup src/index.ts --format esm --dts -d dist",
"test": "vitest --run --coverage",
"typecheck": "tsc"
},
"dependencies": {
"rehype-raw": "^7.0.0",
"rehype-stringify": "^10.0.0",
"remark-parse": "^11.0.0",
"remark-rehype": "^11.1.0",
"unified": "^11.0.4"
},
"peerDependencies": {
"@content-collections/core": "0.x",
"react": "^18.0.0",
"react-dom": "^18.2.0"
},
"devDependencies": {
"@content-collections/core": "workspace:*",
"tsup": "^7.2.0",
"typescript": "^5.3.2",
"vitest": "^1.1.0"
}
}
115 changes: 115 additions & 0 deletions packages/markdown/src/index.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,115 @@
import { describe, expect, it } from "vitest";
import { compileMarkdown } from ".";
import { Context, Meta } from "@content-collections/core";

type Cache = Context["cache"];

const cache: Cache = (input, fn) => {
return fn(input) as any;
};

const sampleMeta: Meta = {
directory: "post",
extension: ".mdx",
filePath: "post/index.mdx",
fileName: "index",
path: "/post",
};

describe("markdown", () => {
it("should convert markdown to html", async () => {
const html = await compileMarkdown(
{ cache },
{
_meta: sampleMeta,
content: "# Hello World!",
}
);

expect(html).toBe("<h1>Hello World!</h1>");
});

it("should apply remark plugins", async () => {
const html = await compileMarkdown(
{ cache },
{
_meta: sampleMeta,
content: "# Hello World!",
},
{
remarkPlugins: [
() => (tree) => {
tree.children[0].children[0].value = "Hello Universe!";
},
],
}
);

expect(html).toBe("<h1>Hello Universe!</h1>");
});

it("should apply rehype plugins", async () => {
const html = await compileMarkdown(
{ cache },
{
_meta: sampleMeta,
content: "# Hello World!",
},
{
rehypePlugins: [
() => (tree) => {
tree.children[0].children[0].value = "Hello Universe!";
},
],
}
);

expect(html).toBe("<h1>Hello Universe!</h1>");
});

it("should add meta to vfile data", async () => {
const html = await compileMarkdown(
{ cache },
{
_meta: sampleMeta,
content: "# Hello World!",
},
{
remarkPlugins: [
() => (tree, vfile) => {
// @ts-ignore - vfile data is not typed
tree.children[0].children[0].value = `Hello from ${vfile.data._meta.path}`;
},
],
}
);

expect(html).toBe("<h1>Hello from /post</h1>");
});

it("should not allow html in markdown", async () => {
const html = await compileMarkdown(
{ cache },
{
_meta: sampleMeta,
content: "# Hello <strong>World</strong>!",
}
);

expect(html).toBe("<h1>Hello World!</h1>");
});

it("should allow html in markdown", async () => {
const html = await compileMarkdown(
{ cache },
{
_meta: sampleMeta,
content: "# Hello <strong>World</strong>!",
},{
allowDangerousHtml: true
}
);

expect(html).toBe("<h1>Hello <strong>World</strong>!</h1>");
});
});
53 changes: 53 additions & 0 deletions packages/markdown/src/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
import { Context, Meta } from "@content-collections/core";
import rehypeStringify from "rehype-stringify";
import remarkParse from "remark-parse";
import remarkRehype from "remark-rehype";
import rehypeRaw from "rehype-raw";
import { Pluggable, Transformer, unified } from "unified";

type Document = {
_meta: Meta;
content: string;
};

type Options = {
allowDangerousHtml?: boolean;
remarkPlugins?: Pluggable[];
rehypePlugins?: Pluggable[];
};

function addMetaToVFile(_meta: Meta) {
return (): Transformer => (_, vFile) => {
Object.assign(vFile.data, { _meta });
};
}

async function compile(document: Document, options?: Options) {
const builder = unified().use(remarkParse);
builder.use(addMetaToVFile(document._meta));

if (options?.remarkPlugins) {
builder.use(options.remarkPlugins);
}

builder.use(remarkRehype, { allowDangerousHtml: options?.allowDangerousHtml });
if (options?.allowDangerousHtml) {
builder.use(rehypeRaw);
}

if (options?.rehypePlugins) {
builder.use(options.rehypePlugins);
}

const html = await builder.use(rehypeStringify).process(document.content);

return String(html);
}

export function compileMarkdown(
{ cache }: Pick<Context, "cache">,
document: Document,
options?: Options
) {
return cache(document, (doc) => compile(doc, options));
}
22 changes: 22 additions & 0 deletions packages/markdown/tsconfig.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
{
"compilerOptions": {
/* Base Options: */
"esModuleInterop": true,
"skipLibCheck": true,
"target": "es2022",
"allowJs": true,
"resolveJsonModule": true,
"moduleDetection": "force",
"isolatedModules": true,
/* Strictness */
"strict": true,
"noUncheckedIndexedAccess": true,
/* If NOT transpiling with TypeScript: */
"moduleResolution": "Bundler",
"module": "ESNext",
"noEmit": true,
/* If your code doesn't run in the DOM: */
"lib": ["es2022"],
},
"include": ["src/**/*"]
}
Loading

0 comments on commit 2ba1bac

Please sign in to comment.