diff options
Diffstat (limited to 'packages/integrations/markdoc')
22 files changed, 185 insertions, 48 deletions
diff --git a/packages/integrations/markdoc/CHANGELOG.md b/packages/integrations/markdoc/CHANGELOG.md index 0929ce6e0..978f2ba91 100644 --- a/packages/integrations/markdoc/CHANGELOG.md +++ b/packages/integrations/markdoc/CHANGELOG.md @@ -1,5 +1,38 @@ # @astrojs/markdoc +## 0.11.5-beta.1 + +### Patch Changes + +- [#12075](https://github.com/withastro/astro/pull/12075) [`a19530e`](https://github.com/withastro/astro/commit/a19530e377b7d7afad58a33b23c0a5df1c376819) Thanks [@bluwy](https://github.com/bluwy)! - Parses frontmatter ourselves + +- Updated dependencies [[`a19530e`](https://github.com/withastro/astro/commit/a19530e377b7d7afad58a33b23c0a5df1c376819)]: + - @astrojs/markdown-remark@6.0.0-beta.2 + +## 0.11.5-beta.0 + +### Patch Changes + +- Updated dependencies [[`5608338`](https://github.com/withastro/astro/commit/560833843c6d3ce2b6c6c473ec4ae70e744bf255)]: + - @astrojs/markdown-remark@6.0.0-beta.1 + +## 1.0.0-alpha.1 + +### Patch Changes + +- [#11825](https://github.com/withastro/astro/pull/11825) [`560ef15`](https://github.com/withastro/astro/commit/560ef15ad23bd137b56ef1048eb2df548b99fdce) Thanks [@bluwy](https://github.com/bluwy)! - Uses latest version of `@astrojs/markdown-remark` with updated Shiki APIs + +- Updated dependencies [[`3ab3b4e`](https://github.com/withastro/astro/commit/3ab3b4efbcdd2aabea5f949deedf51a5acefae59), [`560ef15`](https://github.com/withastro/astro/commit/560ef15ad23bd137b56ef1048eb2df548b99fdce), [`3ab3b4e`](https://github.com/withastro/astro/commit/3ab3b4efbcdd2aabea5f949deedf51a5acefae59)]: + - @astrojs/markdown-remark@6.0.0-alpha.1 + +## 1.0.0-alpha.0 + +### Patch Changes + +- Updated dependencies [[`b6fbdaa`](https://github.com/withastro/astro/commit/b6fbdaa94a9ecec706a99e1938fbf5cd028c72e0), [`89bab1e`](https://github.com/withastro/astro/commit/89bab1e70786123fbe933a9d7a1b80c9334dcc5f), [`d74617c`](https://github.com/withastro/astro/commit/d74617cbd3278feba05909ec83db2d73d57a153e), [`83a2a64`](https://github.com/withastro/astro/commit/83a2a648418ad30f4eb781d1c1b5f2d8a8ac846e), [`e90f559`](https://github.com/withastro/astro/commit/e90f5593d23043579611452a84b9e18ad2407ef9), [`2df49a6`](https://github.com/withastro/astro/commit/2df49a6fb4f6d92fe45f7429430abe63defeacd6), [`8a53517`](https://github.com/withastro/astro/commit/8a5351737d6a14fc55f1dafad8f3b04079e81af6)]: + - astro@5.0.0-alpha.0 + - @astrojs/markdown-remark@6.0.0-alpha.0 + ## 0.11.5 ### Patch Changes diff --git a/packages/integrations/markdoc/package.json b/packages/integrations/markdoc/package.json index 282a1e9e4..80c4e7771 100644 --- a/packages/integrations/markdoc/package.json +++ b/packages/integrations/markdoc/package.json @@ -1,7 +1,7 @@ { "name": "@astrojs/markdoc", "description": "Add support for Markdoc in your Astro site", - "version": "0.11.5", + "version": "0.12.0-beta.0", "type": "module", "types": "./dist/index.d.ts", "author": "withastro", @@ -68,11 +68,10 @@ "@markdoc/markdoc": "^0.4.0", "esbuild": "^0.21.5", "github-slugger": "^2.0.0", - "gray-matter": "^4.0.3", "htmlparser2": "^9.1.0" }, "peerDependencies": { - "astro": "^3.0.0 || ^4.0.0" + "astro": "^5.0.0-alpha.0" }, "devDependencies": { "@types/markdown-it": "^14.1.2", @@ -80,10 +79,10 @@ "astro-scripts": "workspace:*", "devalue": "^5.1.1", "linkedom": "^0.18.5", - "vite": "^5.4.11" + "vite": "^6.0.1" }, "engines": { - "node": "^18.17.1 || ^20.3.0 || >=21.0.0" + "node": "^18.17.1 || ^20.3.0 || >=22.0.0" }, "publishConfig": { "provenance": true diff --git a/packages/integrations/markdoc/src/content-entry-type.ts b/packages/integrations/markdoc/src/content-entry-type.ts index 303251d66..67a8be531 100644 --- a/packages/integrations/markdoc/src/content-entry-type.ts +++ b/packages/integrations/markdoc/src/content-entry-type.ts @@ -1,11 +1,11 @@ import fs from 'node:fs'; import path from 'node:path'; import { fileURLToPath, pathToFileURL } from 'node:url'; +import { parseFrontmatter } from '@astrojs/markdown-remark'; import type { Config as MarkdocConfig, Node } from '@markdoc/markdoc'; import Markdoc from '@markdoc/markdoc'; import type { AstroConfig, ContentEntryType } from 'astro'; import { emitESMImage } from 'astro/assets/utils'; -import matter from 'gray-matter'; import type { Rollup, ErrorPayload as ViteErrorPayload } from 'vite'; import type { ComponentConfig } from './config.js'; import { htmlTokenTransform } from './html/transform/html-token-transform.js'; @@ -26,12 +26,20 @@ export async function getContentEntryType({ }): Promise<ContentEntryType> { return { extensions: ['.mdoc'], - getEntryInfo, + getEntryInfo({ fileUrl, contents }) { + const parsed = safeParseFrontmatter(contents, fileURLToPath(fileUrl)); + return { + data: parsed.frontmatter, + body: parsed.content.trim(), + slug: parsed.frontmatter.slug, + rawData: parsed.rawFrontmatter, + }; + }, handlePropagation: true, async getRenderModule({ contents, fileUrl, viteId }) { - const entry = getEntryInfo({ contents, fileUrl }); + const parsed = safeParseFrontmatter(contents, fileURLToPath(fileUrl)); const tokenizer = getMarkdocTokenizer(options); - let tokens = tokenizer.tokenize(entry.body); + let tokens = tokenizer.tokenize(parsed.content); if (options?.allowHTML) { tokens = htmlTokenTransform(tokenizer, tokens); @@ -47,7 +55,6 @@ export async function getContentEntryType({ ast, /* Raised generics issue with Markdoc core https://github.com/markdoc/markdoc/discussions/400 */ markdocConfig: markdocConfig as MarkdocConfig, - entry, viteId, astroConfig, filePath, @@ -64,7 +71,6 @@ export async function getContentEntryType({ raiseValidationErrors({ ast: partialAst, markdocConfig: markdocConfig as MarkdocConfig, - entry, viteId, astroConfig, filePath: partialPath, @@ -224,14 +230,12 @@ async function resolvePartials({ function raiseValidationErrors({ ast, markdocConfig, - entry, viteId, astroConfig, filePath, }: { ast: Node; markdocConfig: MarkdocConfig; - entry: ReturnType<typeof getEntryInfo>; viteId: string; astroConfig: AstroConfig; filePath: string; @@ -250,8 +254,6 @@ function raiseValidationErrors({ }); if (validationErrors.length) { - // Heuristic: take number of newlines for `rawData` and add 2 for the `---` fences - const frontmatterBlockOffset = entry.rawData.split('\n').length + 2; const rootRelativePath = path.relative(fileURLToPath(astroConfig.root), filePath); throw new MarkdocError({ message: [ @@ -261,7 +263,7 @@ function raiseValidationErrors({ location: { // Error overlay does not support multi-line or ranges. // Just point to the first line. - line: frontmatterBlockOffset + validationErrors[0].lines[0], + line: validationErrors[0].lines[0], file: viteId, }, }); @@ -282,16 +284,6 @@ function getUsedTags(markdocAst: Node) { return tags; } -function getEntryInfo({ fileUrl, contents }: { fileUrl: URL; contents: string }) { - const parsed = parseFrontmatter(contents, fileURLToPath(fileUrl)); - return { - data: parsed.data, - body: parsed.content, - slug: parsed.data.slug, - rawData: parsed.matter, - }; -} - /** * Emits optimized images, and appends the generated `src` to each AST node * via the `__optimizedSrc` attribute. @@ -410,12 +402,11 @@ function getStringifiedMap( * Match YAML exception handling from Astro core errors * @see 'astro/src/core/errors.ts' */ -function parseFrontmatter(fileContents: string, filePath: string) { +function safeParseFrontmatter(fileContents: string, filePath: string) { try { - // `matter` is empty string on cache results - // clear cache to prevent this - (matter as any).clearCache(); - return matter(fileContents); + // empty with lines to preserve sourcemap location, but not `empty-with-spaces` + // because markdoc struggles with spaces + return parseFrontmatter(fileContents, { frontmatter: 'empty-with-lines' }); } catch (e: any) { if (e.name === 'YAMLException') { const err: Error & ViteErrorPayload['err'] = e; diff --git a/packages/integrations/markdoc/src/extensions/shiki.ts b/packages/integrations/markdoc/src/extensions/shiki.ts index 04fc8e867..1102242fd 100644 --- a/packages/integrations/markdoc/src/extensions/shiki.ts +++ b/packages/integrations/markdoc/src/extensions/shiki.ts @@ -5,7 +5,11 @@ import { unescapeHTML } from 'astro/runtime/server/index.js'; import type { AstroMarkdocConfig } from '../config.js'; export default async function shiki(config?: ShikiConfig): Promise<AstroMarkdocConfig> { - const highlighter = await createShikiHighlighter(config); + const highlighter = await createShikiHighlighter({ + langs: config?.langs, + theme: config?.theme, + themes: config?.themes, + }); return { nodes: { @@ -16,7 +20,11 @@ export default async function shiki(config?: ShikiConfig): Promise<AstroMarkdocC // Only the `js` part is parsed as `attributes.language` and the rest is ignored. This means // some Shiki transformers may not work correctly as it relies on the `meta`. const lang = typeof attributes.language === 'string' ? attributes.language : 'plaintext'; - const html = await highlighter.highlight(attributes.content, lang); + const html = await highlighter.codeToHtml(attributes.content, lang, { + wrap: config?.wrap, + defaultColor: config?.defaultColor, + transformers: config?.transformers, + }); // Use `unescapeHTML` to return `HTMLString` for Astro renderer to inline as HTML return unescapeHTML(html) as any; diff --git a/packages/integrations/markdoc/test/content-collections.test.js b/packages/integrations/markdoc/test/content-collections.test.js index 5417f297d..48e97d45d 100644 --- a/packages/integrations/markdoc/test/content-collections.test.js +++ b/packages/integrations/markdoc/test/content-collections.test.js @@ -13,6 +13,8 @@ function formatPost(post) { const root = new URL('./fixtures/content-collections/', import.meta.url); +const sortById = (a, b) => a.id.localeCompare(b.id); + describe('Markdoc - Content Collections', () => { let baseFixture; @@ -46,7 +48,7 @@ describe('Markdoc - Content Collections', () => { assert.notEqual(posts, null); assert.deepEqual( - posts.sort().map((post) => formatPost(post)), + posts.sort(sortById).map((post) => formatPost(post)), [post1Entry, post2Entry, post3Entry], ); }); @@ -68,7 +70,7 @@ describe('Markdoc - Content Collections', () => { const posts = parseDevalue(res); assert.notEqual(posts, null); assert.deepEqual( - posts.sort().map((post) => formatPost(post)), + posts.sort(sortById).map((post) => formatPost(post)), [post1Entry, post2Entry, post3Entry], ); }); @@ -83,7 +85,10 @@ const post1Entry = { schemaWorks: true, title: 'Post 1', }, - body: '\n## Post 1\n\nThis is the contents of post 1.\n', + body: '## Post 1\n\nThis is the contents of post 1.', + deferredRender: true, + filePath: 'src/content/blog/post-1.mdoc', + digest: '5d5bd98d949e2b9a', }; const post2Entry = { @@ -94,7 +99,10 @@ const post2Entry = { schemaWorks: true, title: 'Post 2', }, - body: '\n## Post 2\n\nThis is the contents of post 2.\n', + body: '## Post 2\n\nThis is the contents of post 2.', + deferredRender: true, + filePath: 'src/content/blog/post-2.mdoc', + digest: '595af4b93a4af072', }; const post3Entry = { @@ -105,5 +113,8 @@ const post3Entry = { schemaWorks: true, title: 'Post 3', }, - body: '\n## Post 3\n\nThis is the contents of post 3.\n', + body: '## Post 3\n\nThis is the contents of post 3.', + deferredRender: true, + filePath: 'src/content/blog/post-3.mdoc', + digest: 'ef589606e542247e', }; diff --git a/packages/integrations/markdoc/test/fixtures/headings-custom/src/content/config.ts b/packages/integrations/markdoc/test/fixtures/headings-custom/src/content/config.ts new file mode 100644 index 000000000..a142ace11 --- /dev/null +++ b/packages/integrations/markdoc/test/fixtures/headings-custom/src/content/config.ts @@ -0,0 +1,7 @@ +import { defineCollection } from 'astro:content'; + +const docs = defineCollection({}); + +export const collections = { + docs, +}; diff --git a/packages/integrations/markdoc/test/fixtures/headings/src/content/config.ts b/packages/integrations/markdoc/test/fixtures/headings/src/content/config.ts new file mode 100644 index 000000000..a142ace11 --- /dev/null +++ b/packages/integrations/markdoc/test/fixtures/headings/src/content/config.ts @@ -0,0 +1,7 @@ +import { defineCollection } from 'astro:content'; + +const docs = defineCollection({}); + +export const collections = { + docs, +}; diff --git a/packages/integrations/markdoc/test/fixtures/image-assets/src/content/config.ts b/packages/integrations/markdoc/test/fixtures/image-assets/src/content/config.ts new file mode 100644 index 000000000..a142ace11 --- /dev/null +++ b/packages/integrations/markdoc/test/fixtures/image-assets/src/content/config.ts @@ -0,0 +1,7 @@ +import { defineCollection } from 'astro:content'; + +const docs = defineCollection({}); + +export const collections = { + docs, +}; diff --git a/packages/integrations/markdoc/test/fixtures/image-assets/tsconfig.json b/packages/integrations/markdoc/test/fixtures/image-assets/tsconfig.json index b5bf6a715..c193287fc 100644 --- a/packages/integrations/markdoc/test/fixtures/image-assets/tsconfig.json +++ b/packages/integrations/markdoc/test/fixtures/image-assets/tsconfig.json @@ -5,5 +5,7 @@ "paths": { "~/assets/*": ["src/assets/*"] }, - } + }, + "include": [".astro/types.d.ts", "**/*"], + "exclude": ["dist"] } diff --git a/packages/integrations/markdoc/test/fixtures/render with-space/src/content/config.ts b/packages/integrations/markdoc/test/fixtures/render with-space/src/content/config.ts new file mode 100644 index 000000000..629486e48 --- /dev/null +++ b/packages/integrations/markdoc/test/fixtures/render with-space/src/content/config.ts @@ -0,0 +1,7 @@ +import { defineCollection } from 'astro:content'; + +const blog = defineCollection({}); + +export const collections = { + blog, +}; diff --git a/packages/integrations/markdoc/test/fixtures/render-html/src/content/config.ts b/packages/integrations/markdoc/test/fixtures/render-html/src/content/config.ts new file mode 100644 index 000000000..629486e48 --- /dev/null +++ b/packages/integrations/markdoc/test/fixtures/render-html/src/content/config.ts @@ -0,0 +1,7 @@ +import { defineCollection } from 'astro:content'; + +const blog = defineCollection({}); + +export const collections = { + blog, +}; diff --git a/packages/integrations/markdoc/test/fixtures/render-null/src/content/config.ts b/packages/integrations/markdoc/test/fixtures/render-null/src/content/config.ts new file mode 100644 index 000000000..629486e48 --- /dev/null +++ b/packages/integrations/markdoc/test/fixtures/render-null/src/content/config.ts @@ -0,0 +1,7 @@ +import { defineCollection } from 'astro:content'; + +const blog = defineCollection({}); + +export const collections = { + blog, +}; diff --git a/packages/integrations/markdoc/test/fixtures/render-partials/src/content/config.ts b/packages/integrations/markdoc/test/fixtures/render-partials/src/content/config.ts new file mode 100644 index 000000000..629486e48 --- /dev/null +++ b/packages/integrations/markdoc/test/fixtures/render-partials/src/content/config.ts @@ -0,0 +1,7 @@ +import { defineCollection } from 'astro:content'; + +const blog = defineCollection({}); + +export const collections = { + blog, +}; diff --git a/packages/integrations/markdoc/test/fixtures/render-simple/src/content/config.ts b/packages/integrations/markdoc/test/fixtures/render-simple/src/content/config.ts new file mode 100644 index 000000000..629486e48 --- /dev/null +++ b/packages/integrations/markdoc/test/fixtures/render-simple/src/content/config.ts @@ -0,0 +1,7 @@ +import { defineCollection } from 'astro:content'; + +const blog = defineCollection({}); + +export const collections = { + blog, +}; diff --git a/packages/integrations/markdoc/test/fixtures/render-typographer/src/content/config.ts b/packages/integrations/markdoc/test/fixtures/render-typographer/src/content/config.ts new file mode 100644 index 000000000..629486e48 --- /dev/null +++ b/packages/integrations/markdoc/test/fixtures/render-typographer/src/content/config.ts @@ -0,0 +1,7 @@ +import { defineCollection } from 'astro:content'; + +const blog = defineCollection({}); + +export const collections = { + blog, +}; diff --git a/packages/integrations/markdoc/test/fixtures/render-with-components/src/content/config.ts b/packages/integrations/markdoc/test/fixtures/render-with-components/src/content/config.ts new file mode 100644 index 000000000..629486e48 --- /dev/null +++ b/packages/integrations/markdoc/test/fixtures/render-with-components/src/content/config.ts @@ -0,0 +1,7 @@ +import { defineCollection } from 'astro:content'; + +const blog = defineCollection({}); + +export const collections = { + blog, +}; diff --git a/packages/integrations/markdoc/test/fixtures/render-with-components/tsconfig.json b/packages/integrations/markdoc/test/fixtures/render-with-components/tsconfig.json index 99df2e61a..f993eddf6 100644 --- a/packages/integrations/markdoc/test/fixtures/render-with-components/tsconfig.json +++ b/packages/integrations/markdoc/test/fixtures/render-with-components/tsconfig.json @@ -3,5 +3,7 @@ "compilerOptions": { "jsx": "react-jsx", "jsxImportSource": "preact" - } + }, + "include": [".astro/types.d.ts", "**/*"], + "exclude": ["dist"] }
\ No newline at end of file diff --git a/packages/integrations/markdoc/test/fixtures/render-with-config/src/content/config.ts b/packages/integrations/markdoc/test/fixtures/render-with-config/src/content/config.ts new file mode 100644 index 000000000..629486e48 --- /dev/null +++ b/packages/integrations/markdoc/test/fixtures/render-with-config/src/content/config.ts @@ -0,0 +1,7 @@ +import { defineCollection } from 'astro:content'; + +const blog = defineCollection({}); + +export const collections = { + blog, +}; diff --git a/packages/integrations/markdoc/test/fixtures/render-with-extends-components/src/content/config.ts b/packages/integrations/markdoc/test/fixtures/render-with-extends-components/src/content/config.ts new file mode 100644 index 000000000..629486e48 --- /dev/null +++ b/packages/integrations/markdoc/test/fixtures/render-with-extends-components/src/content/config.ts @@ -0,0 +1,7 @@ +import { defineCollection } from 'astro:content'; + +const blog = defineCollection({}); + +export const collections = { + blog, +}; diff --git a/packages/integrations/markdoc/test/fixtures/render-with-indented-components/src/content/config.ts b/packages/integrations/markdoc/test/fixtures/render-with-indented-components/src/content/config.ts new file mode 100644 index 000000000..629486e48 --- /dev/null +++ b/packages/integrations/markdoc/test/fixtures/render-with-indented-components/src/content/config.ts @@ -0,0 +1,7 @@ +import { defineCollection } from 'astro:content'; + +const blog = defineCollection({}); + +export const collections = { + blog, +}; diff --git a/packages/integrations/markdoc/test/image-assets.test.js b/packages/integrations/markdoc/test/image-assets.test.js index 0f98af4f1..793bf1be6 100644 --- a/packages/integrations/markdoc/test/image-assets.test.js +++ b/packages/integrations/markdoc/test/image-assets.test.js @@ -38,7 +38,7 @@ describe('Markdoc - Image assets', () => { const { document } = parseHTML(html); assert.match( document.querySelector('#relative > img')?.src, - /\/_image\?href=.*%2Fsrc%2Fassets%2Frelative%2Foar.jpg%3ForigWidth%3D420%26origHeight%3D630%26origFormat%3Djpg&f=webp/, + /\/_image\?href=.*%2Fsrc%2Fassets%2Frelative%2Foar.jpg%3ForigWidth%3D420%26origHeight%3D630%26origFormat%3Djpg&w=420&h=630&f=webp/, ); }); @@ -48,7 +48,7 @@ describe('Markdoc - Image assets', () => { const { document } = parseHTML(html); assert.match( document.querySelector('#alias > img')?.src, - /\/_image\?href=.*%2Fsrc%2Fassets%2Falias%2Fcityscape.jpg%3ForigWidth%3D420%26origHeight%3D280%26origFormat%3Djpg&f=webp/, + /\/_image\?href=.*%2Fsrc%2Fassets%2Falias%2Fcityscape.jpg%3ForigWidth%3D420%26origHeight%3D280%26origFormat%3Djpg&w=420&h=280&f=webp/, ); }); diff --git a/packages/integrations/markdoc/test/propagated-assets.test.js b/packages/integrations/markdoc/test/propagated-assets.test.js index a0768448f..5fe7369ce 100644 --- a/packages/integrations/markdoc/test/propagated-assets.test.js +++ b/packages/integrations/markdoc/test/propagated-assets.test.js @@ -45,12 +45,12 @@ describe('Markdoc - propagated assets', () => { let styleContents; if (mode === 'dev') { const styles = stylesDocument.querySelectorAll('style'); - assert.equal(styles.length, 1); - styleContents = styles[0].textContent; + assert.equal(styles.length, 2); + styleContents = styles[1].textContent; } else { const links = stylesDocument.querySelectorAll('link[rel="stylesheet"]'); - assert.equal(links.length, 1); - styleContents = await fixture.readFile(links[0].href); + assert.equal(links.length, 2); + styleContents = await fixture.readFile(links[1].href); } assert.equal(styleContents.includes('--color-base-purple: 269, 79%;'), true); }); @@ -58,10 +58,10 @@ describe('Markdoc - propagated assets', () => { it('[fails] Does not bleed styles to other page', async () => { if (mode === 'dev') { const styles = scriptsDocument.querySelectorAll('style'); - assert.equal(styles.length, 0); + assert.equal(styles.length, 1); } else { const links = scriptsDocument.querySelectorAll('link[rel="stylesheet"]'); - assert.equal(links.length, 0); + assert.equal(links.length, 1); } }); }); |