Skip to content

Commit

Permalink
Ensure interoperability and portability by letting documents import c…
Browse files Browse the repository at this point in the history
…omponents via frontmatter.
  • Loading branch information
samuelstroschein committed Dec 28, 2024
1 parent 1dabe46 commit 3c453b5
Show file tree
Hide file tree
Showing 10 changed files with 114 additions and 276 deletions.
5 changes: 5 additions & 0 deletions .changeset/mean-humans-mix.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@opral/markdown-wc": minor
---

Refactor: Remove dependency on TailwindCSS to increase interoperability.
15 changes: 15 additions & 0 deletions .changeset/weak-zebras-smell.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
---
"@opral/markdown-wc": minor
---

Ensure interoperability and portability by letting documents import components via frontmatter.

```diff
title: "Hello World"
+import:
+ - "https://example.com/doc-card.js"
+ - "https://example.com/doc-button.js"
---

# Hello World
```
8 changes: 4 additions & 4 deletions inlang/packages/website/src/pages/m/+onBeforeRender.ts
Original file line number Diff line number Diff line change
Expand Up @@ -120,8 +120,8 @@ export default async function onBeforeRender(pageContext: PageContext) {
const markdown = await parse(content);

renderedMarkdown = markdown.html;
if (markdown.data?.frontmatter) {
pageData = markdown.data?.frontmatter;
if (markdown?.frontmatter) {
pageData = markdown?.frontmatter;
}
} catch (error) {
// pages do not getting prerendered because they are link
Expand All @@ -139,8 +139,8 @@ export default async function onBeforeRender(pageContext: PageContext) {
const readmeMarkdown = await parse(await getContentString(readme()!));

renderedMarkdown = readmeMarkdown.html;
if (readmeMarkdown.data?.frontmatter) {
pageData = readmeMarkdown.data?.frontmatter;
if (readmeMarkdown?.frontmatter) {
pageData = readmeMarkdown?.frontmatter;
}
} catch (error) {
console.error("Error while accessing the readme file");
Expand Down
33 changes: 26 additions & 7 deletions packages/markdown-wc/README.md
Original file line number Diff line number Diff line change
@@ -1,20 +1,29 @@
import:
- "https://example.com/doc-card.js"
- "https://example.com/doc-button.js"


---

# Markdown with Web Components

Enables writing documentation with components in markdown as backwards compatible superset.

## Why

- Enables writing documentation with components in markdown
- Uses only HTML and Frontmatter to be backwards compatible with markdown
- Interoperable with existing markdown parsers
- Doesn't depend on a framework like [React MDX](https://mdxjs.com/) or [Svelte MDsveX](https://github.com/pngwn/MDsveX)
- Doesn't introduce custom syntax like [Markdoc](https://markdoc.dev/)

## Comparison

| Feature | Markdown | @opral/markdown-wc | React MDX | Svelte MDsveX | Markdoc |
|--------------------------------|----------|--------------------|-----------|---------------|---------|
| Components in markdown ||||||
| Interoperable ||||||
| Doesn't depend on a framework ||||||
| Components in markdown ||||||
| Interoperable ||||||
| Portable ||||||
| No custom syntax ||||||


## Usage
Expand All @@ -33,7 +42,17 @@ const markdown = `
</doc-card>
`;

const html = parse(markdown);
// Parse markdown
const parsed = parse(markdown);

// Register web components
for (const name in parsed.imports) {
// optionally sanitize the components here
const component = await import(parsed.imports[name])
customElements.define(name, component);
}

// render HTML
render(parsed.html);
```

console.log(html);
```
3 changes: 0 additions & 3 deletions packages/markdown-wc/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,6 @@
"clean": "rm -rf ./dist ./node_modules"
},
"dependencies": {
"@sinclair/typebox": "^0.32.20",
"cheerio": "1.0.0-rc.12",
"iconify-icon": "1.0.8",
"lit": "2.8.0",
"rehype-accessible-emojis": "0.3.2",
Expand All @@ -32,7 +30,6 @@
"rehype-sanitize": "6.0.0",
"rehype-slug": "6.0.0",
"rehype-stringify": "10.0.0",
"remark-frontmatter": "^5.0.0",
"remark-gfm": "3.0.1",
"remark-parse": "10.0.2",
"remark-rehype": "10.1.0",
Expand Down
1 change: 0 additions & 1 deletion packages/markdown-wc/src/index.ts
Original file line number Diff line number Diff line change
@@ -1,2 +1 @@
export { parse } from "./parse.js"
export { generateTableOfContents } from "./tableOfContents.js"
52 changes: 19 additions & 33 deletions packages/markdown-wc/src/parse.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,57 +33,43 @@ C -->|Two| E[Result two]
expect(html).toContain("<svg")
})

test("should be able to render custom elements", async () => {
test("leaves imported custom elements as is", async () => {
const markdown = `
---
imports:
doc-figure: "https://cdn.skypack.dev/@doc-elements/figure"
---
# Hello World
<doc-figure label="Hello world"></doc-figure>
`
const html = (await parse(markdown)).html
expect(html).toContain("<doc-figure")
const parsed = await parse(markdown)
expect(parsed.html).toContain("<doc-figure")
expect(parsed.frontmatter.imports).toEqual({
"doc-figure": "https://cdn.skypack.dev/@doc-elements/figure",
})
})

test("should be able to provide a badge generator", async () => {
const markdown = `
<inlang-badge-generator></inlang-badge-generator>
`
const html = (await parse(markdown)).html
expect(html).toContain("<inlang-badge-generator></inlang-badge-generator>")
})

test("should be able to display a comment", async () => {
const markdown = `
<doc-comment text="Test comment." name="John Doe"></doc-comment>
`
const html = (await parse(markdown)).html
expect(html).toContain("<doc-comment")
})

test("should be able to use frontmatter", async () => {
test("additional frontmatter properties", async () => {
const markdown = `---
title: test
description: test
title: test_title
description: test_description
---
# Hello World
This is markdown
`
const result = await parse(markdown)
expect(result.html).toContain("<h1")
expect(result.data.frontmatter.title).toBeDefined()
expect(result.frontmatter.title).toEqual("test_title")
expect(result.frontmatter.description).toEqual("test_description")
})

test("should throw if frontmatter type is not valid", async () => {
const markdown = `---
title: test
---
test("no frontmatter defined", async () => {
const markdown = `
# Hello World
This is markdown
`
try {
await parse(markdown)
} catch (e: any) {
expect(e.message).toContain("Frontmatter is not valid")
}
const parsed = await parse(markdown)
expect(parsed.html).toContain("<h1")
})
Loading

0 comments on commit 3c453b5

Please sign in to comment.