@astrojs/markdown-remark 0.13.0 → 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,5 +1,5 @@
1
- @astrojs/markdown-remark:build: cache hit, replaying output a1025d081834f1c0
2
- @astrojs/markdown-remark:build: 
3
- @astrojs/markdown-remark:build: > @astrojs/markdown-remark@0.13.0 build /home/runner/work/astro/astro/packages/markdown/remark
4
- @astrojs/markdown-remark:build: > astro-scripts build "src/**/*.ts" && tsc -p tsconfig.json
5
- @astrojs/markdown-remark:build: 
1
+ @astrojs/markdown-remark:build: cache hit, replaying output 08cb56cbe86045e2
2
+ @astrojs/markdown-remark:build: 
3
+ @astrojs/markdown-remark:build: > @astrojs/markdown-remark@1.0.0 build /home/runner/work/astro/astro/packages/markdown/remark
4
+ @astrojs/markdown-remark:build: > astro-scripts build "src/**/*.ts" && tsc -p tsconfig.json
5
+ @astrojs/markdown-remark:build: 
package/CHANGELOG.md CHANGED
@@ -1,5 +1,39 @@
1
1
  # @astrojs/markdown-remark
2
2
 
3
+ ## 1.0.0
4
+
5
+ ### Major Changes
6
+
7
+ - [`04ad44563`](https://github.com/withastro/astro/commit/04ad445632c67bdd60c1704e1e0dcbcaa27b9308) - > Astro v1.0 is out! Read the [official announcement post](https://astro.build/blog/astro-1/).
8
+
9
+ **No breaking changes**. This package is now officially stable and compatible with `astro@1.0.0`!
10
+
11
+ ### Patch Changes
12
+
13
+ - Updated dependencies [[`04ad44563`](https://github.com/withastro/astro/commit/04ad445632c67bdd60c1704e1e0dcbcaa27b9308)]:
14
+ - @astrojs/prism@1.0.0
15
+
16
+ ## 0.14.1
17
+
18
+ ### Patch Changes
19
+
20
+ - [#4176](https://github.com/withastro/astro/pull/4176) [`2675b8633`](https://github.com/withastro/astro/commit/2675b8633c5d5c45b237ec87940d5eaf1bfb1b4b) Thanks [@bholmesdev](https://github.com/bholmesdev)! - Support frontmatter injection for MD and MDX using remark and rehype plugins
21
+
22
+ * [#4137](https://github.com/withastro/astro/pull/4137) [`471c6f784`](https://github.com/withastro/astro/commit/471c6f784e21399676c8b2002665ffdf83a1c59e) Thanks [@bholmesdev](https://github.com/bholmesdev)! - Speed up internal markdown builds with new vite-plugin markdown
23
+
24
+ - [#4169](https://github.com/withastro/astro/pull/4169) [`16034f0dd`](https://github.com/withastro/astro/commit/16034f0dd5b3683e9e022dbd413e85bd18d2b031) Thanks [@hippotastic](https://github.com/hippotastic)! - Fix double-escaping of non-highlighted code blocks in Astro-flavored markdown
25
+
26
+ ## 0.14.0
27
+
28
+ ### Minor Changes
29
+
30
+ - [#4114](https://github.com/withastro/astro/pull/4114) [`64432bcb8`](https://github.com/withastro/astro/commit/64432bcb873efd0e4297c00fc9583a1fe516dfe7) Thanks [@Princesseuh](https://github.com/Princesseuh)! - Refactor `@astrojs/mdx` and `@astrojs/markdown-remark` to use `@astrojs/prism` instead of duplicating the code
31
+
32
+ ### Patch Changes
33
+
34
+ - Updated dependencies [[`64432bcb8`](https://github.com/withastro/astro/commit/64432bcb873efd0e4297c00fc9583a1fe516dfe7)]:
35
+ - @astrojs/prism@0.7.0
36
+
3
37
  ## 0.13.0
4
38
 
5
39
  ### Minor Changes
package/dist/index.js CHANGED
@@ -5,6 +5,7 @@ import rehypeExpressions from "./rehype-expressions.js";
5
5
  import rehypeIslands from "./rehype-islands.js";
6
6
  import rehypeJsx from "./rehype-jsx.js";
7
7
  import remarkEscape from "./remark-escape.js";
8
+ import { remarkInitializeAstroData } from "./remark-initialize-astro-data.js";
8
9
  import remarkMarkAndUnravel from "./remark-mark-and-unravel.js";
9
10
  import remarkMdxish from "./remark-mdxish.js";
10
11
  import remarkPrism from "./remark-prism.js";
@@ -33,7 +34,7 @@ async function renderMarkdown(content, opts) {
33
34
  const input = new VFile({ value: content, path: fileURL });
34
35
  const scopedClassName = (_a = opts.$) == null ? void 0 : _a.scopedClassName;
35
36
  const { headings, rehypeCollectHeadings } = createCollectHeadings();
36
- let parser = unified().use(markdown).use(isAstroFlavoredMd ? [remarkMdxish, remarkMarkAndUnravel, remarkUnwrap, remarkEscape] : []);
37
+ let parser = unified().use(markdown).use(remarkInitializeAstroData).use(isAstroFlavoredMd ? [remarkMdxish, remarkMarkAndUnravel, remarkUnwrap, remarkEscape] : []);
37
38
  if (remarkPlugins.length === 0 && rehypePlugins.length === 0) {
38
39
  remarkPlugins = [...DEFAULT_REMARK_PLUGINS];
39
40
  rehypePlugins = [...DEFAULT_REHYPE_PLUGINS];
@@ -72,18 +73,18 @@ async function renderMarkdown(content, opts) {
72
73
  parser.use(
73
74
  isAstroFlavoredMd ? [rehypeJsx, rehypeExpressions, rehypeEscape, rehypeIslands, rehypeCollectHeadings] : [rehypeCollectHeadings, rehypeRaw]
74
75
  ).use(rehypeStringify, { allowDangerousHtml: true });
75
- let result;
76
+ let vfile;
76
77
  try {
77
- const vfile = await parser.process(input);
78
- result = vfile.toString();
78
+ vfile = await parser.process(input);
79
79
  } catch (err) {
80
80
  err = prefixError(err, `Failed to parse Markdown file "${input.path}"`);
81
81
  console.error(err);
82
82
  throw err;
83
83
  }
84
84
  return {
85
- metadata: { headings, source: content, html: result.toString() },
86
- code: result.toString()
85
+ metadata: { headings, source: content, html: String(vfile.value) },
86
+ code: String(vfile.value),
87
+ vfile
87
88
  };
88
89
  }
89
90
  function prefixError(err, prefix) {
@@ -1 +1,2 @@
1
+ export declare function escapeEntities(value: string): string;
1
2
  export default function rehypeEscape(): any;
@@ -1,17 +1,21 @@
1
- import { visit } from "unist-util-visit";
1
+ import { SKIP, visit } from "unist-util-visit";
2
+ function escapeEntities(value) {
3
+ return value.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;");
4
+ }
2
5
  function rehypeEscape() {
3
6
  return function(node) {
4
7
  return visit(node, "element", (el) => {
5
8
  if (el.tagName === "code" || el.tagName === "pre") {
6
9
  el.properties["is:raw"] = true;
7
10
  visit(el, "raw", (raw) => {
8
- raw.value = raw.value.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;");
11
+ raw.value = escapeEntities(raw.value);
9
12
  });
13
+ return SKIP;
10
14
  }
11
- return el;
12
15
  });
13
16
  };
14
17
  }
15
18
  export {
16
- rehypeEscape as default
19
+ rehypeEscape as default,
20
+ escapeEntities
17
21
  };
@@ -0,0 +1,2 @@
1
+ import type { VFile } from 'vfile';
2
+ export declare function remarkInitializeAstroData(): (tree: any, vfile: VFile) => void;
@@ -0,0 +1,10 @@
1
+ function remarkInitializeAstroData() {
2
+ return function(tree, vfile) {
3
+ if (!vfile.data.astro) {
4
+ vfile.data.astro = { frontmatter: {} };
5
+ }
6
+ };
7
+ }
8
+ export {
9
+ remarkInitializeAstroData
10
+ };
@@ -1,44 +1,12 @@
1
- import { addAstro } from "@astrojs/prism/internal";
2
- import Prism from "prismjs";
3
- import loadLanguages from "prismjs/components/index.js";
1
+ import { runHighlighterWithAstro } from "@astrojs/prism/dist/highlighter";
4
2
  import { visit } from "unist-util-visit";
5
3
  const noVisit = /* @__PURE__ */ new Set(["root", "html", "text"]);
6
- const languageMap = /* @__PURE__ */ new Map([["ts", "typescript"]]);
7
- function runHighlighter(lang, code) {
8
- let classLanguage = `language-${lang}`;
9
- if (lang == null) {
10
- lang = "plaintext";
11
- }
12
- const ensureLoaded = (language) => {
13
- if (language && !Prism.languages[language]) {
14
- loadLanguages([language]);
15
- }
16
- };
17
- if (languageMap.has(lang)) {
18
- ensureLoaded(languageMap.get(lang));
19
- } else if (lang === "astro") {
20
- ensureLoaded("typescript");
21
- addAstro(Prism);
22
- } else {
23
- ensureLoaded("markup-templating");
24
- ensureLoaded(lang);
25
- }
26
- if (lang && !Prism.languages[lang]) {
27
- console.warn(`Unable to load the language: ${lang}`);
28
- }
29
- const grammar = Prism.languages[lang];
30
- let html = code;
31
- if (grammar) {
32
- html = Prism.highlight(code, grammar, lang);
33
- }
34
- return { classLanguage, html };
35
- }
36
4
  function transformer(className) {
37
5
  return function(tree) {
38
6
  const visitor = (node) => {
39
7
  let { lang, value } = node;
40
8
  node.type = "html";
41
- let { html, classLanguage } = runHighlighter(lang, value);
9
+ let { html, classLanguage } = runHighlighterWithAstro(lang, value);
42
10
  let classes = [classLanguage];
43
11
  if (className) {
44
12
  classes.push(className);
package/dist/types.d.ts CHANGED
@@ -2,6 +2,7 @@ import type * as hast from 'hast';
2
2
  import type * as mdast from 'mdast';
3
3
  import type { ILanguageRegistration, IThemeRegistration, Theme } from 'shiki';
4
4
  import type * as unified from 'unified';
5
+ import type { VFile } from 'vfile';
5
6
  export type { Node } from 'unist';
6
7
  export declare type RemarkPlugin<PluginParameters extends any[] = any[]> = unified.Plugin<PluginParameters, mdast.Root>;
7
8
  export declare type RemarkPlugins = (string | [string, any] | RemarkPlugin | [RemarkPlugin, any])[];
@@ -41,5 +42,6 @@ export interface MarkdownMetadata {
41
42
  }
42
43
  export interface MarkdownRenderingResult {
43
44
  metadata: MarkdownMetadata;
45
+ vfile: VFile;
44
46
  code: string;
45
47
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@astrojs/markdown-remark",
3
- "version": "0.13.0",
3
+ "version": "1.0.0",
4
4
  "type": "module",
5
5
  "author": "withastro",
6
6
  "license": "MIT",
@@ -17,18 +17,15 @@
17
17
  },
18
18
  "dependencies": {
19
19
  "@astrojs/micromark-extension-mdx-jsx": "^1.0.3",
20
- "@astrojs/prism": "^0.6.1",
20
+ "@astrojs/prism": "^1.0.0",
21
21
  "acorn": "^8.7.1",
22
22
  "acorn-jsx": "^5.3.2",
23
- "assert": "^2.0.0",
24
23
  "github-slugger": "^1.4.0",
25
24
  "mdast-util-mdx-expression": "^1.2.1",
26
25
  "mdast-util-mdx-jsx": "^1.2.0",
27
- "mdast-util-to-string": "^3.1.0",
28
26
  "micromark-extension-mdx-expression": "^1.0.3",
29
27
  "micromark-extension-mdx-md": "^1.0.0",
30
28
  "micromark-util-combine-extensions": "^1.0.0",
31
- "prismjs": "^1.28.0",
32
29
  "rehype-raw": "^6.1.1",
33
30
  "rehype-stringify": "^9.0.3",
34
31
  "remark-gfm": "^3.0.1",
@@ -47,9 +44,8 @@
47
44
  "@types/hast": "^2.3.4",
48
45
  "@types/mdast": "^3.0.10",
49
46
  "@types/mocha": "^9.1.1",
50
- "@types/prismjs": "^1.26.0",
51
47
  "@types/unist": "^2.0.6",
52
- "astro-scripts": "0.0.6",
48
+ "astro-scripts": "0.0.7",
53
49
  "chai": "^4.3.6",
54
50
  "micromark-util-types": "^1.0.2",
55
51
  "mocha": "^9.2.2"
package/src/index.ts CHANGED
@@ -7,6 +7,7 @@ import rehypeExpressions from './rehype-expressions.js';
7
7
  import rehypeIslands from './rehype-islands.js';
8
8
  import rehypeJsx from './rehype-jsx.js';
9
9
  import remarkEscape from './remark-escape.js';
10
+ import { remarkInitializeAstroData } from './remark-initialize-astro-data.js';
10
11
  import remarkMarkAndUnravel from './remark-mark-and-unravel.js';
11
12
  import remarkMdxish from './remark-mdxish.js';
12
13
  import remarkPrism from './remark-prism.js';
@@ -45,6 +46,7 @@ export async function renderMarkdown(
45
46
 
46
47
  let parser = unified()
47
48
  .use(markdown)
49
+ .use(remarkInitializeAstroData)
48
50
  .use(isAstroFlavoredMd ? [remarkMdxish, remarkMarkAndUnravel, remarkUnwrap, remarkEscape] : []);
49
51
 
50
52
  if (remarkPlugins.length === 0 && rehypePlugins.length === 0) {
@@ -99,10 +101,9 @@ export async function renderMarkdown(
99
101
  )
100
102
  .use(rehypeStringify, { allowDangerousHtml: true });
101
103
 
102
- let result: string;
104
+ let vfile: VFile;
103
105
  try {
104
- const vfile = await parser.process(input);
105
- result = vfile.toString();
106
+ vfile = await parser.process(input);
106
107
  } catch (err) {
107
108
  // Ensure that the error message contains the input filename
108
109
  // to make it easier for the user to fix the issue
@@ -113,8 +114,9 @@ export async function renderMarkdown(
113
114
  }
114
115
 
115
116
  return {
116
- metadata: { headings, source: content, html: result.toString() },
117
- code: result.toString(),
117
+ metadata: { headings, source: content, html: String(vfile.value) },
118
+ code: String(vfile.value),
119
+ vfile,
118
120
  };
119
121
  }
120
122
 
@@ -1,4 +1,8 @@
1
- import { visit } from 'unist-util-visit';
1
+ import { SKIP, visit } from 'unist-util-visit';
2
+
3
+ export function escapeEntities(value: string): string {
4
+ return value.replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;');
5
+ }
2
6
 
3
7
  export default function rehypeEscape(): any {
4
8
  return function (node: any): any {
@@ -8,10 +12,11 @@ export default function rehypeEscape(): any {
8
12
  // Visit all raw children and escape HTML tags to prevent Markdown code
9
13
  // like "This is a `<script>` tag" from actually opening a script tag
10
14
  visit(el, 'raw', (raw) => {
11
- raw.value = raw.value.replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;');
15
+ raw.value = escapeEntities(raw.value);
12
16
  });
17
+ // Do not visit children to prevent double escaping
18
+ return SKIP;
13
19
  }
14
- return el;
15
20
  });
16
21
  };
17
22
  }
@@ -2,7 +2,7 @@ import type { Literal } from 'unist';
2
2
  import { visit } from 'unist-util-visit';
3
3
 
4
4
  // In code blocks, this removes the JS comment wrapper added to
5
- // HTML comments by vite-plugin-markdown.
5
+ // HTML comments by vite-plugin-markdown-legacy.
6
6
  export default function remarkEscape() {
7
7
  return (tree: any) => {
8
8
  visit(tree, 'code', removeCommentWrapper);
@@ -0,0 +1,9 @@
1
+ import type { VFile } from 'vfile';
2
+
3
+ export function remarkInitializeAstroData() {
4
+ return function (tree: any, vfile: VFile) {
5
+ if (!vfile.data.astro) {
6
+ vfile.data.astro = { frontmatter: {} };
7
+ }
8
+ };
9
+ }
@@ -1,48 +1,7 @@
1
- import { addAstro } from '@astrojs/prism/internal';
2
- import Prism from 'prismjs';
3
- import loadLanguages from 'prismjs/components/index.js';
1
+ import { runHighlighterWithAstro } from '@astrojs/prism/dist/highlighter';
4
2
  import { visit } from 'unist-util-visit';
5
3
  const noVisit = new Set(['root', 'html', 'text']);
6
4
 
7
- const languageMap = new Map([['ts', 'typescript']]);
8
-
9
- function runHighlighter(lang: string, code: string) {
10
- let classLanguage = `language-${lang}`;
11
-
12
- if (lang == null) {
13
- lang = 'plaintext';
14
- }
15
-
16
- const ensureLoaded = (language: string) => {
17
- if (language && !Prism.languages[language]) {
18
- loadLanguages([language]);
19
- }
20
- };
21
-
22
- if (languageMap.has(lang)) {
23
- ensureLoaded(languageMap.get(lang)!);
24
- } else if (lang === 'astro') {
25
- ensureLoaded('typescript');
26
- addAstro(Prism);
27
- } else {
28
- ensureLoaded('markup-templating'); // Prism expects this to exist for a number of other langs
29
- ensureLoaded(lang);
30
- }
31
-
32
- if (lang && !Prism.languages[lang]) {
33
- // eslint-disable-next-line no-console
34
- console.warn(`Unable to load the language: ${lang}`);
35
- }
36
-
37
- const grammar = Prism.languages[lang];
38
- let html = code;
39
- if (grammar) {
40
- html = Prism.highlight(code, grammar, lang);
41
- }
42
-
43
- return { classLanguage, html };
44
- }
45
-
46
5
  type MaybeString = string | null | undefined;
47
6
 
48
7
  /** */
@@ -52,7 +11,7 @@ function transformer(className: MaybeString) {
52
11
  let { lang, value } = node;
53
12
  node.type = 'html';
54
13
 
55
- let { html, classLanguage } = runHighlighter(lang, value);
14
+ let { html, classLanguage } = runHighlighterWithAstro(lang, value);
56
15
  let classes = [classLanguage];
57
16
  if (className) {
58
17
  classes.push(className);
package/src/types.ts CHANGED
@@ -2,6 +2,7 @@ import type * as hast from 'hast';
2
2
  import type * as mdast from 'mdast';
3
3
  import type { ILanguageRegistration, IThemeRegistration, Theme } from 'shiki';
4
4
  import type * as unified from 'unified';
5
+ import type { VFile } from 'vfile';
5
6
 
6
7
  export type { Node } from 'unist';
7
8
 
@@ -58,5 +59,6 @@ export interface MarkdownMetadata {
58
59
 
59
60
  export interface MarkdownRenderingResult {
60
61
  metadata: MarkdownMetadata;
62
+ vfile: VFile;
61
63
  code: string;
62
64
  }
@@ -0,0 +1,23 @@
1
+ import { renderMarkdown } from '../dist/index.js';
2
+ import { expect } from 'chai';
3
+
4
+ describe('entities', () => {
5
+ it('should not unescape entities in regular Markdown', async () => {
6
+ const { code } = await renderMarkdown(`&lt;i&gt;This should NOT be italic&lt;/i&gt;`, {
7
+ isAstroFlavoredMd: false,
8
+ });
9
+
10
+ expect(code).to.equal(`<p>&#x3C;i>This should NOT be italic&#x3C;/i></p>`);
11
+ });
12
+
13
+ it('should not escape entities in code blocks twice in Astro-flavored markdown', async () => {
14
+ const { code } = await renderMarkdown(`\`\`\`astro\n<h1>{x && x.name || ''}!</h1>\n\`\`\``, {
15
+ isAstroFlavoredMd: true,
16
+ syntaxHighlight: false,
17
+ });
18
+
19
+ expect(code).to.equal(
20
+ `<pre is:raw><code class="language-astro">&lt;h1&gt;{x &amp;&amp; x.name || ''}!&lt;/h1&gt;\n</code></pre>`
21
+ );
22
+ });
23
+ });