-
Notifications
You must be signed in to change notification settings - Fork 126
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Support for working with markdown front matter #642
Changes from all commits
3edf564
f0f2b0f
2c51740
fdef72c
c010f50
3decda2
da03986
aef318b
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,34 @@ | ||
--- | ||
title: Markdown | ||
sidebar: | ||
order: 9.2 | ||
keywords: markdown, mdx, frontmatter | ||
--- | ||
|
||
The `MD` class contains several helpers to work with [Markdown](https://www.markdownguide.org/cheat-sheet/) and [frontmatter text](https://jekyllrb.com/docs/front-matter/). | ||
|
||
The parser also support markdown variants like [MDX](https://mdxjs.com/). | ||
|
||
## `frontmatter` | ||
|
||
Extracts and parses the frontmatter text from a markdown file. Returns `undefined` if no frontmatter is not found or the parsing failed. Default format is `yaml`. | ||
|
||
```javascript | ||
const frontmatter = MD.frontmatter(text, "yaml") | ||
``` | ||
|
||
## `content` | ||
|
||
Extracts the markdown source without the frontmatter. | ||
|
||
```javascript | ||
const content = MD.content(text) | ||
``` | ||
|
||
## `updateFrontmatter` | ||
|
||
Merges frontmatter values into the existing in a markdown file. Use `null` value to delete fields. | ||
|
||
```javascript | ||
const updated = MD.updateFrontmatter(text, { title: "New Title" }) | ||
``` |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -129,7 +129,7 @@ | |
... | ||
``` | ||
|
||
You can use the `parsers.frontmatter` to parse out the metadata into an object | ||
You can use the `parsers.frontmatter` or [MD](./md.md) to parse out the metadata into an object | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The relative link to MD documentation should be verified to ensure it correctly points to the md.md file within the same directory.
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The link to MD in "MD" is incorrect. It should be "MD" without the "./" since it's in the same directory.
|
||
|
||
```js | ||
const meta = parsers.frontmatter(file) | ||
|
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,36 +1,84 @@ | ||
import { objectFromMap } from "pdfjs-dist/types/src/shared/util" | ||
import { JSON5TryParse } from "./json5" | ||
import { TOMLTryParse } from "./toml" | ||
import { YAMLTryParse } from "./yaml" | ||
import { YAMLTryParse, YAMLStringify } from "./yaml" | ||
|
||
export function frontmatterTryParse( | ||
text: string, | ||
options?: { format: "yaml" | "json" | "toml" } | ||
): { end: number; value: any } { | ||
if (!text) return undefined | ||
|
||
options?: { format: "yaml" | "json" | "toml" | "text" } | ||
): { text: string; value: any; endLine?: number } | undefined { | ||
const { format = "yaml" } = options || {} | ||
const { frontmatter, endLine } = splitMarkdown(text) | ||
if (!frontmatter) return undefined | ||
|
||
let res: any | ||
switch (format) { | ||
case "text": | ||
res = frontmatter | ||
break | ||
case "json": | ||
res = JSON5TryParse(frontmatter) | ||
break | ||
case "toml": | ||
res = TOMLTryParse(frontmatter) | ||
break | ||
default: | ||
res = YAMLTryParse(frontmatter) | ||
break | ||
} | ||
return { text: frontmatter, value: res, endLine } | ||
} | ||
|
||
export function splitMarkdown(text: string): { | ||
frontmatter?: string | ||
endLine?: number | ||
content: string | ||
} { | ||
if (!text) return { content: text } | ||
const lines = text.split(/\r?\n/g) | ||
const delimiter = "---" | ||
if (lines[0] !== delimiter) return undefined | ||
if (lines[0] !== delimiter) return { content: text } | ||
let end = 1 | ||
while (end < lines.length) { | ||
if (lines[end] === delimiter) break | ||
end++ | ||
} | ||
if (end >= lines.length) return undefined | ||
const fm = lines.slice(1, end).join("\n") | ||
let res: any | ||
if (end >= lines.length) return { content: text } | ||
const frontmatter = lines.slice(1, end).join("\n") | ||
const content = lines.slice(end + 1).join("\n") | ||
return { frontmatter, content, endLine: end } | ||
} | ||
pelikhan marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
export function updateFrontmatter( | ||
text: string, | ||
newFrontmatter: any, | ||
options?: { format: "yaml" | "json" } | ||
): string { | ||
const { content = "" } = splitMarkdown(text) | ||
if (newFrontmatter === null) return content | ||
|
||
const frontmatter = frontmatterTryParse(text, options)?.value ?? {} | ||
|
||
// merge object | ||
for (const [key, value] of Object.entries(newFrontmatter ?? {})) { | ||
if (value === null) { | ||
delete frontmatter[key] | ||
} else { | ||
frontmatter[key] = value | ||
} | ||
Check failure on line 68 in packages/core/src/frontmatter.ts GitHub Actions / build
|
||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The code deletes a key from the
|
||
} | ||
|
||
const { format = "yaml" } = options || {} | ||
let fm: string | ||
switch (format) { | ||
case "json": | ||
res = JSON5TryParse(fm) | ||
fm = JSON.stringify(frontmatter, null, 2) | ||
break | ||
case "toml": | ||
res = TOMLTryParse(fm) | ||
case "yaml": | ||
fm = YAMLStringify(frontmatter) | ||
break | ||
default: | ||
res = YAMLTryParse(fm) | ||
break | ||
throw new Error(`Unsupported format: ${format}`) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The default case in the switch statement throws an error for unsupported formats. However, the function does not handle this error, which could lead to unhandled exceptions. Consider providing a default format or handling this error in a way that does not interrupt the execution of the program. 😊
|
||
} | ||
Check failure on line 82 in packages/core/src/frontmatter.ts GitHub Actions / build
|
||
return res !== undefined ? { end: end + 1, value: res } : undefined | ||
return `---\n${fm}\n---\n${content}` | ||
pelikhan marked this conversation as resolved.
Show resolved
Hide resolved
|
||
} |
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There seems to be a typo here. "no frontmatter is not found" should be "no frontmatter is found".