@astrojs/markdown-remark 5.2.0 → 6.0.0-alpha.1
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.
- package/dist/frontmatter.d.ts +1 -0
- package/dist/frontmatter.js +11 -0
- package/dist/highlight.d.ts +1 -1
- package/dist/highlight.js +10 -5
- package/dist/index.d.ts +2 -2
- package/dist/index.js +19 -20
- package/dist/rehype-collect-headings.js +12 -9
- package/dist/rehype-images.d.ts +2 -2
- package/dist/rehype-images.js +1 -1
- package/dist/rehype-shiki.js +13 -2
- package/dist/remark-collect-images.d.ts +2 -2
- package/dist/remark-collect-images.js +2 -1
- package/dist/shiki.d.ts +40 -10
- package/dist/shiki.js +74 -98
- package/dist/types.d.ts +13 -19
- package/package.json +6 -8
- package/dist/frontmatter-injection.d.ts +0 -6
- package/dist/frontmatter-injection.js +0 -31
- package/dist/internal.d.ts +0 -1
- package/dist/internal.js +0 -5
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function isFrontmatterValid(frontmatter: Record<string, any>): boolean;
|
package/dist/highlight.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import type { Root } from 'hast';
|
|
2
2
|
type Highlighter = (code: string, language: string, options?: {
|
|
3
3
|
meta?: string;
|
|
4
|
-
}) => Promise<string>;
|
|
4
|
+
}) => Promise<Root | string>;
|
|
5
5
|
/**
|
|
6
6
|
* A hast utility to syntax highlight code blocks with a given syntax highlighter.
|
|
7
7
|
*
|
package/dist/highlight.js
CHANGED
|
@@ -16,13 +16,13 @@ async function highlightCodeBlocks(tree, highlighter) {
|
|
|
16
16
|
let languageMatch;
|
|
17
17
|
let { className } = node.properties;
|
|
18
18
|
if (typeof className === "string") {
|
|
19
|
-
languageMatch =
|
|
19
|
+
languageMatch = languagePattern.exec(className);
|
|
20
20
|
} else if (Array.isArray(className)) {
|
|
21
21
|
for (const cls of className) {
|
|
22
22
|
if (typeof cls !== "string") {
|
|
23
23
|
continue;
|
|
24
24
|
}
|
|
25
|
-
languageMatch =
|
|
25
|
+
languageMatch = languagePattern.exec(cls);
|
|
26
26
|
if (languageMatch) {
|
|
27
27
|
break;
|
|
28
28
|
}
|
|
@@ -41,9 +41,14 @@ async function highlightCodeBlocks(tree, highlighter) {
|
|
|
41
41
|
for (const { node, language, grandParent, parent } of nodes) {
|
|
42
42
|
const meta = node.data?.meta ?? node.properties.metastring ?? void 0;
|
|
43
43
|
const code = toText(node, { whitespace: "pre" });
|
|
44
|
-
const
|
|
45
|
-
|
|
46
|
-
|
|
44
|
+
const result = await highlighter(code, language, { meta });
|
|
45
|
+
let replacement;
|
|
46
|
+
if (typeof result === "string") {
|
|
47
|
+
replacement = fromHtml(result, { fragment: true }).children[0];
|
|
48
|
+
removePosition(replacement);
|
|
49
|
+
} else {
|
|
50
|
+
replacement = result.children[0];
|
|
51
|
+
}
|
|
47
52
|
const index = grandParent.children.indexOf(parent);
|
|
48
53
|
grandParent.children[index] = replacement;
|
|
49
54
|
}
|
package/dist/index.d.ts
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import type { AstroMarkdownOptions, MarkdownProcessor } from './types.js';
|
|
2
|
-
export { InvalidAstroDataError, setVfileFrontmatter } from './frontmatter-injection.js';
|
|
3
2
|
export { rehypeHeadingIds } from './rehype-collect-headings.js';
|
|
4
3
|
export { remarkCollectImages } from './remark-collect-images.js';
|
|
5
4
|
export { rehypePrism } from './rehype-prism.js';
|
|
6
5
|
export { rehypeShiki } from './rehype-shiki.js';
|
|
7
|
-
export {
|
|
6
|
+
export { isFrontmatterValid } from './frontmatter.js';
|
|
7
|
+
export { createShikiHighlighter, type ShikiHighlighter, type CreateShikiHighlighterOptions, type ShikiHighlighterHighlightOptions, } from './shiki.js';
|
|
8
8
|
export * from './types.js';
|
|
9
9
|
export declare const markdownConfigDefaults: Required<AstroMarkdownOptions>;
|
|
10
10
|
/**
|
package/dist/index.js
CHANGED
|
@@ -1,8 +1,3 @@
|
|
|
1
|
-
import {
|
|
2
|
-
InvalidAstroDataError,
|
|
3
|
-
safelyGetAstroData,
|
|
4
|
-
setVfileFrontmatter
|
|
5
|
-
} from "./frontmatter-injection.js";
|
|
6
1
|
import { loadPlugins } from "./load-plugins.js";
|
|
7
2
|
import { rehypeHeadingIds } from "./rehype-collect-headings.js";
|
|
8
3
|
import { rehypePrism } from "./rehype-prism.js";
|
|
@@ -17,12 +12,14 @@ import remarkSmartypants from "remark-smartypants";
|
|
|
17
12
|
import { unified } from "unified";
|
|
18
13
|
import { VFile } from "vfile";
|
|
19
14
|
import { rehypeImages } from "./rehype-images.js";
|
|
20
|
-
import { InvalidAstroDataError as InvalidAstroDataError2, setVfileFrontmatter as setVfileFrontmatter2 } from "./frontmatter-injection.js";
|
|
21
15
|
import { rehypeHeadingIds as rehypeHeadingIds2 } from "./rehype-collect-headings.js";
|
|
22
16
|
import { remarkCollectImages as remarkCollectImages2 } from "./remark-collect-images.js";
|
|
23
17
|
import { rehypePrism as rehypePrism2 } from "./rehype-prism.js";
|
|
24
18
|
import { rehypeShiki as rehypeShiki2 } from "./rehype-shiki.js";
|
|
25
|
-
import {
|
|
19
|
+
import { isFrontmatterValid } from "./frontmatter.js";
|
|
20
|
+
import {
|
|
21
|
+
createShikiHighlighter
|
|
22
|
+
} from "./shiki.js";
|
|
26
23
|
export * from "./types.js";
|
|
27
24
|
const markdownConfigDefaults = {
|
|
28
25
|
syntaxHighlight: "shiki",
|
|
@@ -89,23 +86,26 @@ async function createMarkdownProcessor(opts) {
|
|
|
89
86
|
parser.use(rehypeRaw).use(rehypeStringify, { allowDangerousHtml: true });
|
|
90
87
|
return {
|
|
91
88
|
async render(content, renderOpts) {
|
|
92
|
-
const vfile = new VFile({
|
|
93
|
-
|
|
89
|
+
const vfile = new VFile({
|
|
90
|
+
value: content,
|
|
91
|
+
path: renderOpts?.fileURL,
|
|
92
|
+
data: {
|
|
93
|
+
astro: {
|
|
94
|
+
frontmatter: renderOpts?.frontmatter ?? {}
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
});
|
|
94
98
|
const result = await parser.process(vfile).catch((err) => {
|
|
95
99
|
err = prefixError(err, `Failed to parse Markdown file "${vfile.path}"`);
|
|
96
100
|
console.error(err);
|
|
97
101
|
throw err;
|
|
98
102
|
});
|
|
99
|
-
const astroData = safelyGetAstroData(result.data);
|
|
100
|
-
if (astroData instanceof InvalidAstroDataError) {
|
|
101
|
-
throw astroData;
|
|
102
|
-
}
|
|
103
103
|
return {
|
|
104
104
|
code: String(result.value),
|
|
105
105
|
metadata: {
|
|
106
|
-
headings: result.data.
|
|
107
|
-
imagePaths: result.data.imagePaths ??
|
|
108
|
-
frontmatter:
|
|
106
|
+
headings: result.data.astro?.headings ?? [],
|
|
107
|
+
imagePaths: result.data.astro?.imagePaths ?? [],
|
|
108
|
+
frontmatter: result.data.astro?.frontmatter ?? {}
|
|
109
109
|
}
|
|
110
110
|
};
|
|
111
111
|
}
|
|
@@ -117,7 +117,7 @@ function prefixError(err, prefix) {
|
|
|
117
117
|
err.message = `${prefix}:
|
|
118
118
|
${err.message}`;
|
|
119
119
|
return err;
|
|
120
|
-
} catch
|
|
120
|
+
} catch {
|
|
121
121
|
}
|
|
122
122
|
}
|
|
123
123
|
const wrappedError = new Error(`${prefix}${err ? `: ${err}` : ""}`);
|
|
@@ -129,13 +129,12 @@ ${err.message}`;
|
|
|
129
129
|
return wrappedError;
|
|
130
130
|
}
|
|
131
131
|
export {
|
|
132
|
-
InvalidAstroDataError2 as InvalidAstroDataError,
|
|
133
132
|
createMarkdownProcessor,
|
|
134
133
|
createShikiHighlighter,
|
|
134
|
+
isFrontmatterValid,
|
|
135
135
|
markdownConfigDefaults,
|
|
136
136
|
rehypeHeadingIds2 as rehypeHeadingIds,
|
|
137
137
|
rehypePrism2 as rehypePrism,
|
|
138
138
|
rehypeShiki2 as rehypeShiki,
|
|
139
|
-
remarkCollectImages2 as remarkCollectImages
|
|
140
|
-
setVfileFrontmatter2 as setVfileFrontmatter
|
|
139
|
+
remarkCollectImages2 as remarkCollectImages
|
|
141
140
|
};
|
|
@@ -1,19 +1,18 @@
|
|
|
1
1
|
import Slugger from "github-slugger";
|
|
2
2
|
import { visit } from "unist-util-visit";
|
|
3
|
-
import { InvalidAstroDataError, safelyGetAstroData } from "./frontmatter-injection.js";
|
|
4
3
|
const rawNodeTypes = /* @__PURE__ */ new Set(["text", "raw", "mdxTextExpression"]);
|
|
5
4
|
const codeTagNames = /* @__PURE__ */ new Set(["code", "pre"]);
|
|
6
5
|
function rehypeHeadingIds() {
|
|
7
6
|
return function(tree, file) {
|
|
8
7
|
const headings = [];
|
|
8
|
+
const frontmatter = file.data.astro?.frontmatter;
|
|
9
9
|
const slugger = new Slugger();
|
|
10
10
|
const isMDX = isMDXFile(file);
|
|
11
|
-
const astroData = safelyGetAstroData(file.data);
|
|
12
11
|
visit(tree, (node) => {
|
|
13
12
|
if (node.type !== "element") return;
|
|
14
13
|
const { tagName } = node;
|
|
15
14
|
if (tagName[0] !== "h") return;
|
|
16
|
-
const [, level] =
|
|
15
|
+
const [, level] = /h([0-6])/.exec(tagName) ?? [];
|
|
17
16
|
if (!level) return;
|
|
18
17
|
const depth = Number.parseInt(level);
|
|
19
18
|
let text = "";
|
|
@@ -22,17 +21,20 @@ function rehypeHeadingIds() {
|
|
|
22
21
|
return;
|
|
23
22
|
}
|
|
24
23
|
if (child.type === "raw") {
|
|
25
|
-
if (
|
|
24
|
+
if (/^\n?<.*>\n?$/.test(child.value)) {
|
|
26
25
|
return;
|
|
27
26
|
}
|
|
28
27
|
}
|
|
29
28
|
if (rawNodeTypes.has(child.type)) {
|
|
30
29
|
if (isMDX || codeTagNames.has(parent.tagName)) {
|
|
31
30
|
let value = child.value;
|
|
32
|
-
if (isMdxTextExpression(child) &&
|
|
31
|
+
if (isMdxTextExpression(child) && frontmatter) {
|
|
33
32
|
const frontmatterPath = getMdxFrontmatterVariablePath(child);
|
|
34
33
|
if (Array.isArray(frontmatterPath) && frontmatterPath.length > 0) {
|
|
35
|
-
const frontmatterValue = getMdxFrontmatterVariableValue(
|
|
34
|
+
const frontmatterValue = getMdxFrontmatterVariableValue(
|
|
35
|
+
frontmatter,
|
|
36
|
+
frontmatterPath
|
|
37
|
+
);
|
|
36
38
|
if (typeof frontmatterValue === "string") {
|
|
37
39
|
value = frontmatterValue;
|
|
38
40
|
}
|
|
@@ -52,7 +54,8 @@ function rehypeHeadingIds() {
|
|
|
52
54
|
}
|
|
53
55
|
headings.push({ depth, slug: node.properties.id, text });
|
|
54
56
|
});
|
|
55
|
-
file.data.
|
|
57
|
+
file.data.astro ??= {};
|
|
58
|
+
file.data.astro.headings = headings;
|
|
56
59
|
};
|
|
57
60
|
}
|
|
58
61
|
function isMDXFile(file) {
|
|
@@ -74,8 +77,8 @@ function getMdxFrontmatterVariablePath(node) {
|
|
|
74
77
|
if (expression.type !== "Identifier" || expression.name !== "frontmatter") return new Error();
|
|
75
78
|
return expressionPath.reverse();
|
|
76
79
|
}
|
|
77
|
-
function getMdxFrontmatterVariableValue(
|
|
78
|
-
let value =
|
|
80
|
+
function getMdxFrontmatterVariableValue(frontmatter, path) {
|
|
81
|
+
let value = frontmatter;
|
|
79
82
|
for (const key of path) {
|
|
80
83
|
if (!value[key]) return void 0;
|
|
81
84
|
value = value[key];
|
package/dist/rehype-images.d.ts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import type {
|
|
2
|
-
export declare function rehypeImages(): () => (tree: any, file:
|
|
1
|
+
import type { VFile } from 'vfile';
|
|
2
|
+
export declare function rehypeImages(): () => (tree: any, file: VFile) => void;
|
package/dist/rehype-images.js
CHANGED
|
@@ -7,7 +7,7 @@ function rehypeImages() {
|
|
|
7
7
|
if (node.tagName !== "img") return;
|
|
8
8
|
if (node.properties?.src) {
|
|
9
9
|
node.properties.src = decodeURI(node.properties.src);
|
|
10
|
-
if (file.data.imagePaths?.
|
|
10
|
+
if (file.data.astro?.imagePaths?.includes(node.properties.src)) {
|
|
11
11
|
const { ...props } = node.properties;
|
|
12
12
|
const index = imageOccurrenceMap.get(node.properties.src) || 0;
|
|
13
13
|
imageOccurrenceMap.set(node.properties.src, index + 1);
|
package/dist/rehype-shiki.js
CHANGED
|
@@ -3,9 +3,20 @@ import { createShikiHighlighter } from "./shiki.js";
|
|
|
3
3
|
const rehypeShiki = (config) => {
|
|
4
4
|
let highlighterAsync;
|
|
5
5
|
return async (tree) => {
|
|
6
|
-
highlighterAsync ??= createShikiHighlighter(
|
|
6
|
+
highlighterAsync ??= createShikiHighlighter({
|
|
7
|
+
langs: config?.langs,
|
|
8
|
+
theme: config?.theme,
|
|
9
|
+
themes: config?.themes
|
|
10
|
+
});
|
|
7
11
|
const highlighter = await highlighterAsync;
|
|
8
|
-
await highlightCodeBlocks(tree,
|
|
12
|
+
await highlightCodeBlocks(tree, (code, language, options) => {
|
|
13
|
+
return highlighter.codeToHast(code, language, {
|
|
14
|
+
meta: options?.meta,
|
|
15
|
+
wrap: config?.wrap,
|
|
16
|
+
defaultColor: config?.defaultColor,
|
|
17
|
+
transformers: config?.transformers
|
|
18
|
+
});
|
|
19
|
+
});
|
|
9
20
|
};
|
|
10
21
|
};
|
|
11
22
|
export {
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import type {
|
|
2
|
-
export declare function remarkCollectImages(): (tree: any, vfile:
|
|
1
|
+
import type { VFile } from 'vfile';
|
|
2
|
+
export declare function remarkCollectImages(): (tree: any, vfile: VFile) => void;
|
package/dist/shiki.d.ts
CHANGED
|
@@ -1,12 +1,42 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type { Root } from 'hast';
|
|
2
|
+
import { type LanguageRegistration, type ShikiTransformer, type ThemeRegistration, type ThemeRegistrationRaw } from 'shiki';
|
|
3
|
+
import type { ThemePresets } from './types.js';
|
|
2
4
|
export interface ShikiHighlighter {
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
attributes?: Record<string, string>;
|
|
6
|
-
/**
|
|
7
|
-
* Raw `meta` information to be used by Shiki transformers
|
|
8
|
-
*/
|
|
9
|
-
meta?: string;
|
|
10
|
-
}): Promise<string>;
|
|
5
|
+
codeToHast(code: string, lang?: string, options?: ShikiHighlighterHighlightOptions): Promise<Root>;
|
|
6
|
+
codeToHtml(code: string, lang?: string, options?: ShikiHighlighterHighlightOptions): Promise<string>;
|
|
11
7
|
}
|
|
12
|
-
export
|
|
8
|
+
export interface CreateShikiHighlighterOptions {
|
|
9
|
+
langs?: LanguageRegistration[];
|
|
10
|
+
theme?: ThemePresets | ThemeRegistration | ThemeRegistrationRaw;
|
|
11
|
+
themes?: Record<string, ThemePresets | ThemeRegistration | ThemeRegistrationRaw>;
|
|
12
|
+
}
|
|
13
|
+
export interface ShikiHighlighterHighlightOptions {
|
|
14
|
+
/**
|
|
15
|
+
* Generate inline code element only, without the pre element wrapper.
|
|
16
|
+
*/
|
|
17
|
+
inline?: boolean;
|
|
18
|
+
/**
|
|
19
|
+
* Enable word wrapping.
|
|
20
|
+
* - true: enabled.
|
|
21
|
+
* - false: disabled.
|
|
22
|
+
* - null: All overflow styling removed. Code will overflow the element by default.
|
|
23
|
+
*/
|
|
24
|
+
wrap?: boolean | null;
|
|
25
|
+
/**
|
|
26
|
+
* Chooses a theme from the "themes" option that you've defined as the default styling theme.
|
|
27
|
+
*/
|
|
28
|
+
defaultColor?: 'light' | 'dark' | string | false;
|
|
29
|
+
/**
|
|
30
|
+
* Shiki transformers to customize the generated HTML by manipulating the hast tree.
|
|
31
|
+
*/
|
|
32
|
+
transformers?: ShikiTransformer[];
|
|
33
|
+
/**
|
|
34
|
+
* Additional attributes to be added to the root code block element.
|
|
35
|
+
*/
|
|
36
|
+
attributes?: Record<string, string>;
|
|
37
|
+
/**
|
|
38
|
+
* Raw `meta` information to be used by Shiki transformers.
|
|
39
|
+
*/
|
|
40
|
+
meta?: string;
|
|
41
|
+
}
|
|
42
|
+
export declare function createShikiHighlighter({ langs, theme, themes, }?: CreateShikiHighlighterOptions): Promise<ShikiHighlighter>;
|
package/dist/shiki.js
CHANGED
|
@@ -1,126 +1,102 @@
|
|
|
1
1
|
import {
|
|
2
2
|
createCssVariablesTheme,
|
|
3
|
-
|
|
3
|
+
createHighlighter,
|
|
4
4
|
isSpecialLang
|
|
5
5
|
} from "shiki";
|
|
6
|
-
import { visit } from "unist-util-visit";
|
|
7
|
-
const ASTRO_COLOR_REPLACEMENTS = {
|
|
8
|
-
"--astro-code-foreground": "--astro-code-color-text",
|
|
9
|
-
"--astro-code-background": "--astro-code-color-background"
|
|
10
|
-
};
|
|
11
|
-
const COLOR_REPLACEMENT_REGEX = new RegExp(
|
|
12
|
-
`${Object.keys(ASTRO_COLOR_REPLACEMENTS).join("|")}`,
|
|
13
|
-
"g"
|
|
14
|
-
);
|
|
15
6
|
let _cssVariablesTheme;
|
|
16
7
|
const cssVariablesTheme = () => _cssVariablesTheme ?? (_cssVariablesTheme = createCssVariablesTheme({ variablePrefix: "--astro-code-" }));
|
|
17
8
|
async function createShikiHighlighter({
|
|
18
9
|
langs = [],
|
|
19
10
|
theme = "github-dark",
|
|
20
|
-
themes = {}
|
|
21
|
-
defaultColor,
|
|
22
|
-
wrap = false,
|
|
23
|
-
transformers = []
|
|
11
|
+
themes = {}
|
|
24
12
|
} = {}) {
|
|
25
13
|
theme = theme === "css-variables" ? cssVariablesTheme() : theme;
|
|
26
|
-
const highlighter = await
|
|
14
|
+
const highlighter = await createHighlighter({
|
|
27
15
|
langs: ["plaintext", ...langs],
|
|
28
16
|
themes: Object.values(themes).length ? Object.values(themes) : [theme]
|
|
29
17
|
});
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
`[Shiki] The language "${lang}" doesn't exist, falling back to "plaintext".`
|
|
39
|
-
);
|
|
40
|
-
lang = "plaintext";
|
|
41
|
-
}
|
|
18
|
+
async function highlight(code, lang = "plaintext", options, to) {
|
|
19
|
+
const loadedLanguages = highlighter.getLoadedLanguages();
|
|
20
|
+
if (!isSpecialLang(lang) && !loadedLanguages.includes(lang)) {
|
|
21
|
+
try {
|
|
22
|
+
await highlighter.loadLanguage(lang);
|
|
23
|
+
} catch (_err) {
|
|
24
|
+
console.warn(`[Shiki] The language "${lang}" doesn't exist, falling back to "plaintext".`);
|
|
25
|
+
lang = "plaintext";
|
|
42
26
|
}
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
}
|
|
89
|
-
}
|
|
27
|
+
}
|
|
28
|
+
const themeOptions = Object.values(themes).length ? { themes } : { theme };
|
|
29
|
+
const inline = options?.inline ?? false;
|
|
30
|
+
return highlighter[to === "html" ? "codeToHtml" : "codeToHast"](code, {
|
|
31
|
+
...themeOptions,
|
|
32
|
+
defaultColor: options.defaultColor,
|
|
33
|
+
lang,
|
|
34
|
+
// NOTE: while we can spread `options.attributes` here so that Shiki can auto-serialize this as rendered
|
|
35
|
+
// attributes on the top-level tag, it's not clear whether it is fine to pass all attributes as meta, as
|
|
36
|
+
// they're technically not meta, nor parsed from Shiki's `parseMetaString` API.
|
|
37
|
+
meta: options?.meta ? { __raw: options?.meta } : void 0,
|
|
38
|
+
transformers: [
|
|
39
|
+
{
|
|
40
|
+
pre(node) {
|
|
41
|
+
if (inline) {
|
|
42
|
+
node.tagName = "code";
|
|
43
|
+
}
|
|
44
|
+
const {
|
|
45
|
+
class: attributesClass,
|
|
46
|
+
style: attributesStyle,
|
|
47
|
+
...rest
|
|
48
|
+
} = options?.attributes ?? {};
|
|
49
|
+
Object.assign(node.properties, rest);
|
|
50
|
+
const classValue = (normalizePropAsString(node.properties.class) ?? "") + (attributesClass ? ` ${attributesClass}` : "");
|
|
51
|
+
const styleValue = (normalizePropAsString(node.properties.style) ?? "") + (attributesStyle ? `; ${attributesStyle}` : "");
|
|
52
|
+
node.properties.class = classValue.replace(/shiki/g, "astro-code");
|
|
53
|
+
node.properties.dataLanguage = lang;
|
|
54
|
+
if (options.wrap === false || options.wrap === void 0) {
|
|
55
|
+
node.properties.style = styleValue + "; overflow-x: auto;";
|
|
56
|
+
} else if (options.wrap === true) {
|
|
57
|
+
node.properties.style = styleValue + "; overflow-x: auto; white-space: pre-wrap; word-wrap: break-word;";
|
|
58
|
+
}
|
|
59
|
+
},
|
|
60
|
+
line(node) {
|
|
61
|
+
if (lang === "diff") {
|
|
62
|
+
const innerSpanNode = node.children[0];
|
|
63
|
+
const innerSpanTextNode = innerSpanNode?.type === "element" && innerSpanNode.children?.[0];
|
|
64
|
+
if (innerSpanTextNode && innerSpanTextNode.type === "text") {
|
|
65
|
+
const start = innerSpanTextNode.value[0];
|
|
66
|
+
if (start === "+" || start === "-") {
|
|
67
|
+
innerSpanTextNode.value = innerSpanTextNode.value.slice(1);
|
|
68
|
+
innerSpanNode.children.unshift({
|
|
69
|
+
type: "element",
|
|
70
|
+
tagName: "span",
|
|
71
|
+
properties: { style: "user-select: none;" },
|
|
72
|
+
children: [{ type: "text", value: start }]
|
|
73
|
+
});
|
|
90
74
|
}
|
|
91
75
|
}
|
|
92
|
-
},
|
|
93
|
-
code(node) {
|
|
94
|
-
if (inline) {
|
|
95
|
-
return node.children[0];
|
|
96
|
-
}
|
|
97
|
-
},
|
|
98
|
-
root(node) {
|
|
99
|
-
if (Object.values(themes).length) {
|
|
100
|
-
return;
|
|
101
|
-
}
|
|
102
|
-
const themeName = typeof theme === "string" ? theme : theme.name;
|
|
103
|
-
if (themeName === "css-variables") {
|
|
104
|
-
visit(node, "element", (child) => {
|
|
105
|
-
if (child.properties?.style) {
|
|
106
|
-
child.properties.style = replaceCssVariables(child.properties.style);
|
|
107
|
-
}
|
|
108
|
-
});
|
|
109
|
-
}
|
|
110
76
|
}
|
|
111
77
|
},
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
78
|
+
code(node) {
|
|
79
|
+
if (inline) {
|
|
80
|
+
return node.children[0];
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
},
|
|
84
|
+
...options.transformers ?? []
|
|
85
|
+
]
|
|
86
|
+
});
|
|
87
|
+
}
|
|
88
|
+
return {
|
|
89
|
+
codeToHast(code, lang, options = {}) {
|
|
90
|
+
return highlight(code, lang, options, "hast");
|
|
91
|
+
},
|
|
92
|
+
codeToHtml(code, lang, options = {}) {
|
|
93
|
+
return highlight(code, lang, options, "html");
|
|
115
94
|
}
|
|
116
95
|
};
|
|
117
96
|
}
|
|
118
97
|
function normalizePropAsString(value) {
|
|
119
98
|
return Array.isArray(value) ? value.join(" ") : value;
|
|
120
99
|
}
|
|
121
|
-
function replaceCssVariables(str) {
|
|
122
|
-
return str.replace(COLOR_REPLACEMENT_REGEX, (match) => ASTRO_COLOR_REPLACEMENTS[match] || match);
|
|
123
|
-
}
|
|
124
100
|
export {
|
|
125
101
|
createShikiHighlighter
|
|
126
102
|
};
|
package/dist/types.d.ts
CHANGED
|
@@ -1,26 +1,26 @@
|
|
|
1
1
|
import type * as hast from 'hast';
|
|
2
2
|
import type * as mdast from 'mdast';
|
|
3
3
|
import type { Options as RemarkRehypeOptions } from 'remark-rehype';
|
|
4
|
-
import type { BuiltinTheme
|
|
4
|
+
import type { BuiltinTheme } from 'shiki';
|
|
5
5
|
import type * as unified from 'unified';
|
|
6
|
-
import type {
|
|
6
|
+
import type { CreateShikiHighlighterOptions, ShikiHighlighterHighlightOptions } from './shiki.js';
|
|
7
7
|
export type { Node } from 'unist';
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
8
|
+
declare module 'vfile' {
|
|
9
|
+
interface DataMap {
|
|
10
|
+
astro: {
|
|
11
|
+
headings?: MarkdownHeading[];
|
|
12
|
+
imagePaths?: string[];
|
|
13
|
+
frontmatter?: Record<string, any>;
|
|
14
|
+
};
|
|
15
|
+
}
|
|
16
|
+
}
|
|
11
17
|
export type RemarkPlugin<PluginParameters extends any[] = any[]> = unified.Plugin<PluginParameters, mdast.Root>;
|
|
12
18
|
export type RemarkPlugins = (string | [string, any] | RemarkPlugin | [RemarkPlugin, any])[];
|
|
13
19
|
export type RehypePlugin<PluginParameters extends any[] = any[]> = unified.Plugin<PluginParameters, hast.Root>;
|
|
14
20
|
export type RehypePlugins = (string | [string, any] | RehypePlugin | [RehypePlugin, any])[];
|
|
15
21
|
export type RemarkRehype = RemarkRehypeOptions;
|
|
16
22
|
export type ThemePresets = BuiltinTheme | 'css-variables';
|
|
17
|
-
export interface ShikiConfig {
|
|
18
|
-
langs?: LanguageRegistration[];
|
|
19
|
-
theme?: ThemePresets | ThemeRegistration | ThemeRegistrationRaw;
|
|
20
|
-
themes?: Record<string, ThemePresets | ThemeRegistration | ThemeRegistrationRaw>;
|
|
21
|
-
defaultColor?: 'light' | 'dark' | string | false;
|
|
22
|
-
wrap?: boolean | null;
|
|
23
|
-
transformers?: ShikiTransformer[];
|
|
23
|
+
export interface ShikiConfig extends Pick<CreateShikiHighlighterOptions, 'langs' | 'theme' | 'themes'>, Pick<ShikiHighlighterHighlightOptions, 'defaultColor' | 'wrap' | 'transformers'> {
|
|
24
24
|
}
|
|
25
25
|
export interface AstroMarkdownOptions {
|
|
26
26
|
syntaxHighlight?: 'shiki' | 'prism' | false;
|
|
@@ -42,7 +42,7 @@ export interface MarkdownProcessorRenderResult {
|
|
|
42
42
|
code: string;
|
|
43
43
|
metadata: {
|
|
44
44
|
headings: MarkdownHeading[];
|
|
45
|
-
imagePaths:
|
|
45
|
+
imagePaths: string[];
|
|
46
46
|
frontmatter: Record<string, any>;
|
|
47
47
|
};
|
|
48
48
|
}
|
|
@@ -51,9 +51,3 @@ export interface MarkdownHeading {
|
|
|
51
51
|
slug: string;
|
|
52
52
|
text: string;
|
|
53
53
|
}
|
|
54
|
-
export interface MarkdownVFile extends VFile {
|
|
55
|
-
data: Record<string, unknown> & Partial<DataMap> & {
|
|
56
|
-
__astroHeadings?: MarkdownHeading[];
|
|
57
|
-
imagePaths?: Set<string>;
|
|
58
|
-
};
|
|
59
|
-
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@astrojs/markdown-remark",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "6.0.0-alpha.1",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"author": "withastro",
|
|
6
6
|
"license": "MIT",
|
|
@@ -13,8 +13,7 @@
|
|
|
13
13
|
"homepage": "https://astro.build",
|
|
14
14
|
"main": "./dist/index.js",
|
|
15
15
|
"exports": {
|
|
16
|
-
".": "./dist/index.js"
|
|
17
|
-
"./dist/internal.js": "./dist/internal.js"
|
|
16
|
+
".": "./dist/index.js"
|
|
18
17
|
},
|
|
19
18
|
"imports": {
|
|
20
19
|
"#import-plugin": {
|
|
@@ -27,7 +26,7 @@
|
|
|
27
26
|
],
|
|
28
27
|
"dependencies": {
|
|
29
28
|
"github-slugger": "^2.0.0",
|
|
30
|
-
"hast-util-from-html": "^2.0.
|
|
29
|
+
"hast-util-from-html": "^2.0.2",
|
|
31
30
|
"hast-util-to-text": "^4.0.2",
|
|
32
31
|
"import-meta-resolve": "^4.1.0",
|
|
33
32
|
"mdast-util-definitions": "^6.0.0",
|
|
@@ -37,19 +36,19 @@
|
|
|
37
36
|
"remark-parse": "^11.0.0",
|
|
38
37
|
"remark-rehype": "^11.1.0",
|
|
39
38
|
"remark-smartypants": "^3.0.2",
|
|
40
|
-
"shiki": "^1.
|
|
39
|
+
"shiki": "^1.16.1",
|
|
41
40
|
"unified": "^11.0.5",
|
|
42
41
|
"unist-util-remove-position": "^5.0.0",
|
|
43
42
|
"unist-util-visit": "^5.0.0",
|
|
44
43
|
"unist-util-visit-parents": "^6.0.1",
|
|
45
|
-
"vfile": "^6.0.
|
|
44
|
+
"vfile": "^6.0.3",
|
|
46
45
|
"@astrojs/prism": "3.1.0"
|
|
47
46
|
},
|
|
48
47
|
"devDependencies": {
|
|
49
48
|
"@types/estree": "^1.0.5",
|
|
50
49
|
"@types/hast": "^3.0.4",
|
|
51
50
|
"@types/mdast": "^4.0.4",
|
|
52
|
-
"@types/unist": "^3.0.
|
|
51
|
+
"@types/unist": "^3.0.3",
|
|
53
52
|
"esbuild": "^0.21.5",
|
|
54
53
|
"mdast-util-mdx-expression": "^2.0.0",
|
|
55
54
|
"astro-scripts": "0.0.14"
|
|
@@ -61,7 +60,6 @@
|
|
|
61
60
|
"prepublish": "pnpm build",
|
|
62
61
|
"build": "astro-scripts build \"src/**/*.ts\" && tsc -p tsconfig.json",
|
|
63
62
|
"build:ci": "astro-scripts build \"src/**/*.ts\"",
|
|
64
|
-
"postbuild": "astro-scripts copy \"src/**/*.js\"",
|
|
65
63
|
"dev": "astro-scripts dev \"src/**/*.ts\"",
|
|
66
64
|
"test": "astro-scripts test \"test/**/*.test.js\""
|
|
67
65
|
}
|
|
@@ -1,6 +0,0 @@
|
|
|
1
|
-
import type { VFileData as Data, VFile } from 'vfile';
|
|
2
|
-
import type { MarkdownAstroData } from './types.js';
|
|
3
|
-
export declare class InvalidAstroDataError extends TypeError {
|
|
4
|
-
}
|
|
5
|
-
export declare function safelyGetAstroData(vfileData: Data): MarkdownAstroData | InvalidAstroDataError;
|
|
6
|
-
export declare function setVfileFrontmatter(vfile: VFile, frontmatter: Record<string, any>): void;
|
|
@@ -1,31 +0,0 @@
|
|
|
1
|
-
function isValidAstroData(obj) {
|
|
2
|
-
if (typeof obj === "object" && obj !== null && obj.hasOwnProperty("frontmatter")) {
|
|
3
|
-
const { frontmatter } = obj;
|
|
4
|
-
try {
|
|
5
|
-
JSON.stringify(frontmatter);
|
|
6
|
-
} catch {
|
|
7
|
-
return false;
|
|
8
|
-
}
|
|
9
|
-
return typeof frontmatter === "object" && frontmatter !== null;
|
|
10
|
-
}
|
|
11
|
-
return false;
|
|
12
|
-
}
|
|
13
|
-
class InvalidAstroDataError extends TypeError {
|
|
14
|
-
}
|
|
15
|
-
function safelyGetAstroData(vfileData) {
|
|
16
|
-
const { astro } = vfileData;
|
|
17
|
-
if (!astro || !isValidAstroData(astro)) {
|
|
18
|
-
return new InvalidAstroDataError();
|
|
19
|
-
}
|
|
20
|
-
return astro;
|
|
21
|
-
}
|
|
22
|
-
function setVfileFrontmatter(vfile, frontmatter) {
|
|
23
|
-
vfile.data ??= {};
|
|
24
|
-
vfile.data.astro ??= {};
|
|
25
|
-
vfile.data.astro.frontmatter = frontmatter;
|
|
26
|
-
}
|
|
27
|
-
export {
|
|
28
|
-
InvalidAstroDataError,
|
|
29
|
-
safelyGetAstroData,
|
|
30
|
-
setVfileFrontmatter
|
|
31
|
-
};
|
package/dist/internal.d.ts
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export { InvalidAstroDataError, safelyGetAstroData } from './frontmatter-injection.js';
|