-
-
Notifications
You must be signed in to change notification settings - Fork 48
Add support for frontmatter #635
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
base: main
Are you sure you want to change the base?
Changes from all commits
c0c22a0
f11d1fb
639c131
1c46482
a43ab11
ca54b6b
7fe22b0
eb2a82a
d1a65c7
43423b1
bad1342
9883ec5
6438443
0526f0d
48b230d
e284c3d
8a629b2
619536c
5c1caf3
f771fdc
21bef49
2d61827
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,3 @@ | ||
| /** @type {unique symbol} */ | ||
| export const FRONT_MATTER_MARK = Symbol.for("PRETTIER_IS_FRONT_MATTER"); | ||
| export const FRONT_MATTER_VISITOR_KEYS = []; |
|
Member
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. issue (blocking): CLI is telling that these files are not TypeScript files, but JavaScript. You need to use TypeScript.
Author
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. That will be too much for me right now. Thanks for the support. |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,121 @@ | ||
| import replaceNonLineBreaksWithSpace from './replace-non-line-breaks-with-space.js'; | ||
| import { FRONT_MATTER_MARK } from './constants.js'; | ||
|
|
||
| const DELIMITER_LENGTH = 3; | ||
|
|
||
| /** | ||
| @typedef {{ | ||
| index: number, | ||
| // 1-based line number | ||
| line: number, | ||
| // 0-based column number | ||
| column: number, | ||
| }} Position | ||
| @typedef {{ | ||
| language: string, | ||
| explicitLanguage: string | null, | ||
| value: string, | ||
| startDelimiter: string, | ||
| endDelimiter: string, | ||
| raw: string, | ||
| start: Position, | ||
| end: Position, | ||
| [FRONT_MATTER_MARK]: true, | ||
| }} FrontMatter | ||
| */ | ||
|
|
||
| /** | ||
| @param {string} text | ||
| @returns {FrontMatter | undefined} | ||
| */ | ||
| function getFrontMatter(text) { | ||
| const startDelimiter = text.slice(0, DELIMITER_LENGTH); | ||
|
|
||
| if (startDelimiter !== '---' && startDelimiter !== '+++') { | ||
| return; | ||
| } | ||
|
|
||
| const firstLineBreakIndex = text.indexOf('\n', DELIMITER_LENGTH); | ||
| if (firstLineBreakIndex === -1) { | ||
| return; | ||
| } | ||
|
|
||
| const explicitLanguage = text | ||
| .slice(DELIMITER_LENGTH, firstLineBreakIndex) | ||
| .trim(); | ||
|
|
||
| let endDelimiterIndex = text.indexOf( | ||
| `\n${startDelimiter}`, | ||
| firstLineBreakIndex, | ||
| ); | ||
|
|
||
| let language = explicitLanguage; | ||
| if (!language) { | ||
| language = startDelimiter === '+++' ? 'toml' : 'yaml'; | ||
| } | ||
|
|
||
| if ( | ||
| endDelimiterIndex === -1 && | ||
| startDelimiter === '---' && | ||
| language === 'yaml' | ||
| ) { | ||
| // In some markdown processors such as pandoc, | ||
| // "..." can be used as the end delimiter for YAML front-matter. | ||
| endDelimiterIndex = text.indexOf('\n...', firstLineBreakIndex); | ||
| } | ||
|
|
||
| if (endDelimiterIndex === -1) { | ||
| return; | ||
| } | ||
|
|
||
| const frontMatterEndIndex = endDelimiterIndex + 1 + DELIMITER_LENGTH; | ||
|
|
||
| const nextCharacter = text.charAt(frontMatterEndIndex + 1); | ||
| if (!/\s?/.test(nextCharacter)) { | ||
| return; | ||
| } | ||
|
|
||
| const raw = text.slice(0, frontMatterEndIndex); | ||
| /** @type {string[]} */ | ||
| let lines; | ||
|
|
||
| return { | ||
| language, | ||
| explicitLanguage: explicitLanguage || null, | ||
| value: text.slice(firstLineBreakIndex + 1, endDelimiterIndex), | ||
| startDelimiter, | ||
| endDelimiter: raw.slice(-DELIMITER_LENGTH), | ||
| raw, | ||
| start: { line: 1, column: 0, index: 0 }, | ||
| end: { | ||
| index: raw.length, | ||
| get line() { | ||
| lines ??= raw.split('\n'); | ||
| return lines.length; | ||
| }, | ||
| get column() { | ||
| lines ??= raw.split('\n'); | ||
| return lines.at(-1).length; | ||
| }, | ||
| }, | ||
| [FRONT_MATTER_MARK]: true, | ||
| }; | ||
| } | ||
|
|
||
| function parse(text) { | ||
| const frontMatter = getFrontMatter(text); | ||
|
|
||
| if (!frontMatter) { | ||
| return { content: text }; | ||
| } | ||
|
|
||
| return { | ||
| frontMatter, | ||
| get content() { | ||
| const { raw } = frontMatter; | ||
| return replaceNonLineBreaksWithSpace(raw) + text.slice(raw.length); | ||
| }, | ||
| }; | ||
| } | ||
|
|
||
| export default parse; |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,19 @@ | ||
| // import * as assert from "#universal/assert"; | ||
|
Author
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. I have no idea how to put it back |
||
|
|
||
| /** | ||
| Replaces all characters in the input string except line breaks `\n` with a space. | ||
| @param {string} string - The input string to process. | ||
| @returns {string} | ||
| */ | ||
| function replaceNonLineBreaksWithSpace(string) { | ||
| const replaced = string.replaceAll(/[^\n]/g, ' '); | ||
|
|
||
| if (process.env.NODE_ENV !== 'production') { | ||
| // assert.equal(replaced.length, string.length); | ||
| } | ||
|
|
||
| return replaced; | ||
| } | ||
|
|
||
| export default replaceNonLineBreaksWithSpace; | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,33 @@ | ||
| --- | ||
| name: YAML test | ||
| tags: | ||
| - this | ||
| - squence | ||
| - should | ||
| - be | ||
| - indented | ||
| lets: | ||
| have: | ||
| us: | ||
| some: nesting | ||
| and: some more | ||
| flow style not supported: | ||
| key: value | ||
| bar: baz | ||
| not even arrays: | ||
| - 1 | ||
| - 2 | ||
| - 3 | ||
| - 4 | ||
| - 5 | ||
| --- | ||
| doctype | ||
| html | ||
| head | ||
| title This is a !{ name }! | ||
|
|
||
| body | ||
| h1 Hello world! | ||
| h2= name | ||
|
|
||
| #example |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,9 @@ | ||
| import { compareFiles } from 'tests/common'; | ||
| import { describe, expect, it } from 'vitest'; | ||
|
|
||
| describe('Frontmatter', () => { | ||
| it('should format yaml frontmatter', async () => { | ||
| const { expected, actual } = await compareFiles(import.meta.url); | ||
| expect(actual).toBe(expected); | ||
| }); | ||
| }); |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,27 @@ | ||
| --- | ||
| name: YAML test | ||
| tags: | ||
| - this | ||
| - squence | ||
| - should | ||
| - be | ||
| - indented | ||
| lets: | ||
| have: | ||
| us: | ||
| some: nesting | ||
| and: some more | ||
| flow style not supported: | ||
| {key: value, bar: baz} | ||
| not even arrays: [1,2,3,4,5] | ||
| --- | ||
| doctype | ||
| html | ||
| head | ||
| title This is a !{name}! | ||
|
|
||
| body | ||
| h1 Hello world! | ||
| h2= name | ||
|
|
||
| div( id='example' ) |
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.
this should enforce formatting of flow style array and dict but it doesn't and I don't know why.