@astrojs/markdown-remark 0.0.0-assets-uint8array-20231109073138
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/LICENSE +61 -0
- package/dist/frontmatter-injection.d.ts +12 -0
- package/dist/frontmatter-injection.js +41 -0
- package/dist/index.d.ts +18 -0
- package/dist/index.js +157 -0
- package/dist/internal.d.ts +1 -0
- package/dist/internal.js +10 -0
- package/dist/load-plugins.d.ts +2 -0
- package/dist/load-plugins.js +31 -0
- package/dist/rehype-collect-headings.d.ts +2 -0
- package/dist/rehype-collect-headings.js +97 -0
- package/dist/rehype-images.d.ts +2 -0
- package/dist/rehype-images.js +20 -0
- package/dist/remark-collect-images.d.ts +2 -0
- package/dist/remark-collect-images.js +38 -0
- package/dist/remark-prism.d.ts +2 -0
- package/dist/remark-prism.js +19 -0
- package/dist/remark-shiki.d.ts +2 -0
- package/dist/remark-shiki.js +84 -0
- package/dist/types.d.ts +78 -0
- package/dist/types.js +0 -0
- package/package.json +64 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2021 Fred K. Schott
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
"""
|
|
25
|
+
This license applies to parts of the `packages/create-astro` and `packages/astro` subdirectories originating from the https://github.com/sveltejs/kit repository:
|
|
26
|
+
|
|
27
|
+
Copyright (c) 2020 [these people](https://github.com/sveltejs/kit/graphs/contributors)
|
|
28
|
+
|
|
29
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
|
30
|
+
|
|
31
|
+
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
|
32
|
+
|
|
33
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
34
|
+
"""
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
"""
|
|
38
|
+
This license applies to parts of the `packages/create-astro` and `packages/astro` subdirectories originating from the https://github.com/vitejs/vite repository:
|
|
39
|
+
|
|
40
|
+
MIT License
|
|
41
|
+
|
|
42
|
+
Copyright (c) 2019-present, Yuxi (Evan) You and Vite contributors
|
|
43
|
+
|
|
44
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
45
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
46
|
+
in the Software without restriction, including without limitation the rights
|
|
47
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
48
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
49
|
+
furnished to do so, subject to the following conditions:
|
|
50
|
+
|
|
51
|
+
The above copyright notice and this permission notice shall be included in all
|
|
52
|
+
copies or substantial portions of the Software.
|
|
53
|
+
|
|
54
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
55
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
56
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
57
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
58
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
59
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
60
|
+
SOFTWARE.
|
|
61
|
+
"""
|
|
@@ -0,0 +1,12 @@
|
|
|
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;
|
|
7
|
+
/**
|
|
8
|
+
* @deprecated Use `setVfileFrontmatter` instead
|
|
9
|
+
*/
|
|
10
|
+
export declare function toRemarkInitializeAstroData({ userFrontmatter, }: {
|
|
11
|
+
userFrontmatter: Record<string, any>;
|
|
12
|
+
}): () => (tree: any, vfile: VFile) => void;
|
|
@@ -0,0 +1,41 @@
|
|
|
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
|
+
function toRemarkInitializeAstroData({
|
|
28
|
+
userFrontmatter
|
|
29
|
+
}) {
|
|
30
|
+
return () => function(tree, vfile) {
|
|
31
|
+
if (!vfile.data.astro) {
|
|
32
|
+
vfile.data.astro = { frontmatter: userFrontmatter };
|
|
33
|
+
}
|
|
34
|
+
};
|
|
35
|
+
}
|
|
36
|
+
export {
|
|
37
|
+
InvalidAstroDataError,
|
|
38
|
+
safelyGetAstroData,
|
|
39
|
+
setVfileFrontmatter,
|
|
40
|
+
toRemarkInitializeAstroData
|
|
41
|
+
};
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import type { AstroMarkdownOptions, MarkdownProcessor, MarkdownRenderingOptions, MarkdownRenderingResult } from './types.js';
|
|
2
|
+
export { InvalidAstroDataError, setVfileFrontmatter } from './frontmatter-injection.js';
|
|
3
|
+
export { rehypeHeadingIds } from './rehype-collect-headings.js';
|
|
4
|
+
export { remarkCollectImages } from './remark-collect-images.js';
|
|
5
|
+
export { remarkPrism } from './remark-prism.js';
|
|
6
|
+
export { remarkShiki } from './remark-shiki.js';
|
|
7
|
+
export * from './types.js';
|
|
8
|
+
export declare const markdownConfigDefaults: Omit<Required<AstroMarkdownOptions>, 'drafts'>;
|
|
9
|
+
/**
|
|
10
|
+
* Create a markdown preprocessor to render multiple markdown files
|
|
11
|
+
*/
|
|
12
|
+
export declare function createMarkdownProcessor(opts?: AstroMarkdownOptions): Promise<MarkdownProcessor>;
|
|
13
|
+
/**
|
|
14
|
+
* Shared utility for rendering markdown
|
|
15
|
+
*
|
|
16
|
+
* @deprecated Use `createMarkdownProcessor` instead for better performance
|
|
17
|
+
*/
|
|
18
|
+
export declare function renderMarkdown(content: string, opts: MarkdownRenderingOptions): Promise<MarkdownRenderingResult>;
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,157 @@
|
|
|
1
|
+
import {
|
|
2
|
+
InvalidAstroDataError,
|
|
3
|
+
safelyGetAstroData,
|
|
4
|
+
setVfileFrontmatter
|
|
5
|
+
} from "./frontmatter-injection.js";
|
|
6
|
+
import { loadPlugins } from "./load-plugins.js";
|
|
7
|
+
import { rehypeHeadingIds } from "./rehype-collect-headings.js";
|
|
8
|
+
import { remarkCollectImages } from "./remark-collect-images.js";
|
|
9
|
+
import { remarkPrism } from "./remark-prism.js";
|
|
10
|
+
import { remarkShiki } from "./remark-shiki.js";
|
|
11
|
+
import rehypeRaw from "rehype-raw";
|
|
12
|
+
import rehypeStringify from "rehype-stringify";
|
|
13
|
+
import remarkGfm from "remark-gfm";
|
|
14
|
+
import remarkParse from "remark-parse";
|
|
15
|
+
import remarkRehype from "remark-rehype";
|
|
16
|
+
import remarkSmartypants from "remark-smartypants";
|
|
17
|
+
import { unified } from "unified";
|
|
18
|
+
import { VFile } from "vfile";
|
|
19
|
+
import { rehypeImages } from "./rehype-images.js";
|
|
20
|
+
import { InvalidAstroDataError as InvalidAstroDataError2, setVfileFrontmatter as setVfileFrontmatter2 } from "./frontmatter-injection.js";
|
|
21
|
+
import { rehypeHeadingIds as rehypeHeadingIds2 } from "./rehype-collect-headings.js";
|
|
22
|
+
import { remarkCollectImages as remarkCollectImages2 } from "./remark-collect-images.js";
|
|
23
|
+
import { remarkPrism as remarkPrism2 } from "./remark-prism.js";
|
|
24
|
+
import { remarkShiki as remarkShiki2 } from "./remark-shiki.js";
|
|
25
|
+
export * from "./types.js";
|
|
26
|
+
const markdownConfigDefaults = {
|
|
27
|
+
syntaxHighlight: "shiki",
|
|
28
|
+
shikiConfig: {
|
|
29
|
+
langs: [],
|
|
30
|
+
theme: "github-dark",
|
|
31
|
+
experimentalThemes: {},
|
|
32
|
+
wrap: false
|
|
33
|
+
},
|
|
34
|
+
remarkPlugins: [],
|
|
35
|
+
rehypePlugins: [],
|
|
36
|
+
remarkRehype: {},
|
|
37
|
+
gfm: true,
|
|
38
|
+
smartypants: true
|
|
39
|
+
};
|
|
40
|
+
const isPerformanceBenchmark = Boolean(process.env.ASTRO_PERFORMANCE_BENCHMARK);
|
|
41
|
+
async function createMarkdownProcessor(opts) {
|
|
42
|
+
const {
|
|
43
|
+
syntaxHighlight = markdownConfigDefaults.syntaxHighlight,
|
|
44
|
+
shikiConfig = markdownConfigDefaults.shikiConfig,
|
|
45
|
+
remarkPlugins = markdownConfigDefaults.remarkPlugins,
|
|
46
|
+
rehypePlugins = markdownConfigDefaults.rehypePlugins,
|
|
47
|
+
remarkRehype: remarkRehypeOptions = markdownConfigDefaults.remarkRehype,
|
|
48
|
+
gfm = markdownConfigDefaults.gfm,
|
|
49
|
+
smartypants = markdownConfigDefaults.smartypants
|
|
50
|
+
} = opts ?? {};
|
|
51
|
+
const loadedRemarkPlugins = await Promise.all(loadPlugins(remarkPlugins));
|
|
52
|
+
const loadedRehypePlugins = await Promise.all(loadPlugins(rehypePlugins));
|
|
53
|
+
const parser = unified().use(remarkParse);
|
|
54
|
+
if (!isPerformanceBenchmark) {
|
|
55
|
+
if (gfm) {
|
|
56
|
+
parser.use(remarkGfm);
|
|
57
|
+
}
|
|
58
|
+
if (smartypants) {
|
|
59
|
+
parser.use(remarkSmartypants);
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
for (const [plugin, pluginOpts] of loadedRemarkPlugins) {
|
|
63
|
+
parser.use(plugin, pluginOpts);
|
|
64
|
+
}
|
|
65
|
+
if (!isPerformanceBenchmark) {
|
|
66
|
+
if (syntaxHighlight === "shiki") {
|
|
67
|
+
parser.use(remarkShiki, shikiConfig);
|
|
68
|
+
} else if (syntaxHighlight === "prism") {
|
|
69
|
+
parser.use(remarkPrism);
|
|
70
|
+
}
|
|
71
|
+
parser.use(remarkCollectImages);
|
|
72
|
+
}
|
|
73
|
+
parser.use(remarkRehype, {
|
|
74
|
+
allowDangerousHtml: true,
|
|
75
|
+
passThrough: [],
|
|
76
|
+
...remarkRehypeOptions
|
|
77
|
+
});
|
|
78
|
+
for (const [plugin, pluginOpts] of loadedRehypePlugins) {
|
|
79
|
+
parser.use(plugin, pluginOpts);
|
|
80
|
+
}
|
|
81
|
+
parser.use(rehypeImages());
|
|
82
|
+
if (!isPerformanceBenchmark) {
|
|
83
|
+
parser.use(rehypeHeadingIds);
|
|
84
|
+
}
|
|
85
|
+
parser.use(rehypeRaw).use(rehypeStringify, { allowDangerousHtml: true });
|
|
86
|
+
return {
|
|
87
|
+
async render(content, renderOpts) {
|
|
88
|
+
const vfile = new VFile({ value: content, path: renderOpts?.fileURL });
|
|
89
|
+
setVfileFrontmatter(vfile, renderOpts?.frontmatter ?? {});
|
|
90
|
+
const result = await parser.process(vfile).catch((err) => {
|
|
91
|
+
err = prefixError(err, `Failed to parse Markdown file "${vfile.path}"`);
|
|
92
|
+
console.error(err);
|
|
93
|
+
throw err;
|
|
94
|
+
});
|
|
95
|
+
const astroData = safelyGetAstroData(result.data);
|
|
96
|
+
if (astroData instanceof InvalidAstroDataError) {
|
|
97
|
+
throw astroData;
|
|
98
|
+
}
|
|
99
|
+
return {
|
|
100
|
+
code: String(result.value),
|
|
101
|
+
metadata: {
|
|
102
|
+
headings: result.data.__astroHeadings ?? [],
|
|
103
|
+
imagePaths: result.data.imagePaths ?? /* @__PURE__ */ new Set(),
|
|
104
|
+
frontmatter: astroData.frontmatter ?? {}
|
|
105
|
+
},
|
|
106
|
+
// Compat for `renderMarkdown` only. Do not use!
|
|
107
|
+
__renderMarkdownCompat: {
|
|
108
|
+
result
|
|
109
|
+
}
|
|
110
|
+
};
|
|
111
|
+
}
|
|
112
|
+
};
|
|
113
|
+
}
|
|
114
|
+
async function renderMarkdown(content, opts) {
|
|
115
|
+
const processor = await createMarkdownProcessor(opts);
|
|
116
|
+
const result = await processor.render(content, {
|
|
117
|
+
fileURL: opts.fileURL,
|
|
118
|
+
frontmatter: opts.frontmatter
|
|
119
|
+
});
|
|
120
|
+
return {
|
|
121
|
+
code: result.code,
|
|
122
|
+
metadata: {
|
|
123
|
+
headings: result.metadata.headings,
|
|
124
|
+
source: content,
|
|
125
|
+
html: result.code
|
|
126
|
+
},
|
|
127
|
+
vfile: result.__renderMarkdownCompat.result
|
|
128
|
+
};
|
|
129
|
+
}
|
|
130
|
+
function prefixError(err, prefix) {
|
|
131
|
+
if (err?.message) {
|
|
132
|
+
try {
|
|
133
|
+
err.message = `${prefix}:
|
|
134
|
+
${err.message}`;
|
|
135
|
+
return err;
|
|
136
|
+
} catch (error) {
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
const wrappedError = new Error(`${prefix}${err ? `: ${err}` : ""}`);
|
|
140
|
+
try {
|
|
141
|
+
wrappedError.stack = err.stack;
|
|
142
|
+
wrappedError.cause = err;
|
|
143
|
+
} catch {
|
|
144
|
+
}
|
|
145
|
+
return wrappedError;
|
|
146
|
+
}
|
|
147
|
+
export {
|
|
148
|
+
InvalidAstroDataError2 as InvalidAstroDataError,
|
|
149
|
+
createMarkdownProcessor,
|
|
150
|
+
markdownConfigDefaults,
|
|
151
|
+
rehypeHeadingIds2 as rehypeHeadingIds,
|
|
152
|
+
remarkCollectImages2 as remarkCollectImages,
|
|
153
|
+
remarkPrism2 as remarkPrism,
|
|
154
|
+
remarkShiki2 as remarkShiki,
|
|
155
|
+
renderMarkdown,
|
|
156
|
+
setVfileFrontmatter2 as setVfileFrontmatter
|
|
157
|
+
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { InvalidAstroDataError, safelyGetAstroData, toRemarkInitializeAstroData, } from './frontmatter-injection.js';
|
package/dist/internal.js
ADDED
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { resolve as importMetaResolve } from "import-meta-resolve";
|
|
2
|
+
import path from "node:path";
|
|
3
|
+
import { pathToFileURL } from "node:url";
|
|
4
|
+
const cwdUrlStr = pathToFileURL(path.join(process.cwd(), "package.json")).toString();
|
|
5
|
+
async function importPlugin(p) {
|
|
6
|
+
if (typeof p === "string") {
|
|
7
|
+
try {
|
|
8
|
+
const importResult2 = await import(p);
|
|
9
|
+
return importResult2.default;
|
|
10
|
+
} catch {
|
|
11
|
+
}
|
|
12
|
+
const resolved = importMetaResolve(p, cwdUrlStr);
|
|
13
|
+
const importResult = await import(resolved);
|
|
14
|
+
return importResult.default;
|
|
15
|
+
}
|
|
16
|
+
return p;
|
|
17
|
+
}
|
|
18
|
+
function loadPlugins(items) {
|
|
19
|
+
return items.map((p) => {
|
|
20
|
+
return new Promise((resolve, reject) => {
|
|
21
|
+
if (Array.isArray(p)) {
|
|
22
|
+
const [plugin, opts] = p;
|
|
23
|
+
return importPlugin(plugin).then((m) => resolve([m, opts])).catch((e) => reject(e));
|
|
24
|
+
}
|
|
25
|
+
return importPlugin(p).then((m) => resolve([m])).catch((e) => reject(e));
|
|
26
|
+
});
|
|
27
|
+
});
|
|
28
|
+
}
|
|
29
|
+
export {
|
|
30
|
+
loadPlugins
|
|
31
|
+
};
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
import Slugger from "github-slugger";
|
|
2
|
+
import { visit } from "unist-util-visit";
|
|
3
|
+
import { InvalidAstroDataError, safelyGetAstroData } from "./frontmatter-injection.js";
|
|
4
|
+
const rawNodeTypes = /* @__PURE__ */ new Set(["text", "raw", "mdxTextExpression"]);
|
|
5
|
+
const codeTagNames = /* @__PURE__ */ new Set(["code", "pre"]);
|
|
6
|
+
function rehypeHeadingIds() {
|
|
7
|
+
return function(tree, file) {
|
|
8
|
+
const headings = [];
|
|
9
|
+
const slugger = new Slugger();
|
|
10
|
+
const isMDX = isMDXFile(file);
|
|
11
|
+
const astroData = safelyGetAstroData(file.data);
|
|
12
|
+
visit(tree, (node) => {
|
|
13
|
+
if (node.type !== "element")
|
|
14
|
+
return;
|
|
15
|
+
const { tagName } = node;
|
|
16
|
+
if (tagName[0] !== "h")
|
|
17
|
+
return;
|
|
18
|
+
const [, level] = tagName.match(/h([0-6])/) ?? [];
|
|
19
|
+
if (!level)
|
|
20
|
+
return;
|
|
21
|
+
const depth = Number.parseInt(level);
|
|
22
|
+
let text = "";
|
|
23
|
+
visit(node, (child, __, parent) => {
|
|
24
|
+
if (child.type === "element" || parent == null) {
|
|
25
|
+
return;
|
|
26
|
+
}
|
|
27
|
+
if (child.type === "raw") {
|
|
28
|
+
if (child.value.match(/^\n?<.*>\n?$/)) {
|
|
29
|
+
return;
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
if (rawNodeTypes.has(child.type)) {
|
|
33
|
+
if (isMDX || codeTagNames.has(parent.tagName)) {
|
|
34
|
+
let value = child.value;
|
|
35
|
+
if (isMdxTextExpression(child) && !(astroData instanceof InvalidAstroDataError)) {
|
|
36
|
+
const frontmatterPath = getMdxFrontmatterVariablePath(child);
|
|
37
|
+
if (Array.isArray(frontmatterPath) && frontmatterPath.length > 0) {
|
|
38
|
+
const frontmatterValue = getMdxFrontmatterVariableValue(astroData, frontmatterPath);
|
|
39
|
+
if (typeof frontmatterValue === "string") {
|
|
40
|
+
value = frontmatterValue;
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
text += value;
|
|
45
|
+
} else {
|
|
46
|
+
text += child.value.replace(/\{/g, "${");
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
});
|
|
50
|
+
node.properties = node.properties || {};
|
|
51
|
+
if (typeof node.properties.id !== "string") {
|
|
52
|
+
let slug = slugger.slug(text);
|
|
53
|
+
if (slug.endsWith("-"))
|
|
54
|
+
slug = slug.slice(0, -1);
|
|
55
|
+
node.properties.id = slug;
|
|
56
|
+
}
|
|
57
|
+
headings.push({ depth, slug: node.properties.id, text });
|
|
58
|
+
});
|
|
59
|
+
file.data.__astroHeadings = headings;
|
|
60
|
+
};
|
|
61
|
+
}
|
|
62
|
+
function isMDXFile(file) {
|
|
63
|
+
return Boolean(file.history[0]?.endsWith(".mdx"));
|
|
64
|
+
}
|
|
65
|
+
function getMdxFrontmatterVariablePath(node) {
|
|
66
|
+
if (!node.data?.estree || node.data.estree.body.length !== 1)
|
|
67
|
+
return new Error();
|
|
68
|
+
const statement = node.data.estree.body[0];
|
|
69
|
+
if (statement?.type !== "ExpressionStatement" || statement.expression.type !== "MemberExpression")
|
|
70
|
+
return new Error();
|
|
71
|
+
let expression = statement.expression;
|
|
72
|
+
const expressionPath = [];
|
|
73
|
+
while (expression.type === "MemberExpression" && expression.property.type === (expression.computed ? "Literal" : "Identifier")) {
|
|
74
|
+
expressionPath.push(
|
|
75
|
+
expression.property.type === "Literal" ? String(expression.property.value) : expression.property.name
|
|
76
|
+
);
|
|
77
|
+
expression = expression.object;
|
|
78
|
+
}
|
|
79
|
+
if (expression.type !== "Identifier" || expression.name !== "frontmatter")
|
|
80
|
+
return new Error();
|
|
81
|
+
return expressionPath.reverse();
|
|
82
|
+
}
|
|
83
|
+
function getMdxFrontmatterVariableValue(astroData, path) {
|
|
84
|
+
let value = astroData.frontmatter;
|
|
85
|
+
for (const key of path) {
|
|
86
|
+
if (!value[key])
|
|
87
|
+
return void 0;
|
|
88
|
+
value = value[key];
|
|
89
|
+
}
|
|
90
|
+
return value;
|
|
91
|
+
}
|
|
92
|
+
function isMdxTextExpression(node) {
|
|
93
|
+
return node.type === "mdxTextExpression";
|
|
94
|
+
}
|
|
95
|
+
export {
|
|
96
|
+
rehypeHeadingIds
|
|
97
|
+
};
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { visit } from "unist-util-visit";
|
|
2
|
+
function rehypeImages() {
|
|
3
|
+
return () => function(tree, file) {
|
|
4
|
+
visit(tree, (node) => {
|
|
5
|
+
if (node.type !== "element")
|
|
6
|
+
return;
|
|
7
|
+
if (node.tagName !== "img")
|
|
8
|
+
return;
|
|
9
|
+
if (node.properties?.src) {
|
|
10
|
+
if (file.data.imagePaths?.has(node.properties.src)) {
|
|
11
|
+
node.properties["__ASTRO_IMAGE_"] = node.properties.src;
|
|
12
|
+
delete node.properties.src;
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
});
|
|
16
|
+
};
|
|
17
|
+
}
|
|
18
|
+
export {
|
|
19
|
+
rehypeImages
|
|
20
|
+
};
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import { definitions } from "mdast-util-definitions";
|
|
2
|
+
import { visit } from "unist-util-visit";
|
|
3
|
+
function remarkCollectImages() {
|
|
4
|
+
return function(tree, vfile) {
|
|
5
|
+
if (typeof vfile?.path !== "string")
|
|
6
|
+
return;
|
|
7
|
+
const definition = definitions(tree);
|
|
8
|
+
const imagePaths = /* @__PURE__ */ new Set();
|
|
9
|
+
visit(tree, ["image", "imageReference"], (node) => {
|
|
10
|
+
if (node.type === "image") {
|
|
11
|
+
if (shouldOptimizeImage(node.url))
|
|
12
|
+
imagePaths.add(node.url);
|
|
13
|
+
}
|
|
14
|
+
if (node.type === "imageReference") {
|
|
15
|
+
const imageDefinition = definition(node.identifier);
|
|
16
|
+
if (imageDefinition) {
|
|
17
|
+
if (shouldOptimizeImage(imageDefinition.url))
|
|
18
|
+
imagePaths.add(imageDefinition.url);
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
});
|
|
22
|
+
vfile.data.imagePaths = imagePaths;
|
|
23
|
+
};
|
|
24
|
+
}
|
|
25
|
+
function shouldOptimizeImage(src) {
|
|
26
|
+
return !isValidUrl(src) && !src.startsWith("/");
|
|
27
|
+
}
|
|
28
|
+
function isValidUrl(str) {
|
|
29
|
+
try {
|
|
30
|
+
new URL(str);
|
|
31
|
+
return true;
|
|
32
|
+
} catch {
|
|
33
|
+
return false;
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
export {
|
|
37
|
+
remarkCollectImages
|
|
38
|
+
};
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { runHighlighterWithAstro } from "@astrojs/prism/dist/highlighter";
|
|
2
|
+
import { visit } from "unist-util-visit";
|
|
3
|
+
function remarkPrism() {
|
|
4
|
+
return function(tree) {
|
|
5
|
+
visit(tree, "code", (node) => {
|
|
6
|
+
let { lang, value } = node;
|
|
7
|
+
node.type = "html";
|
|
8
|
+
let { html, classLanguage } = runHighlighterWithAstro(lang, value);
|
|
9
|
+
let classes = [classLanguage];
|
|
10
|
+
node.value = `<pre class="${classes.join(
|
|
11
|
+
" "
|
|
12
|
+
)}"><code is:raw class="${classLanguage}">${html}</code></pre>`;
|
|
13
|
+
return node;
|
|
14
|
+
});
|
|
15
|
+
};
|
|
16
|
+
}
|
|
17
|
+
export {
|
|
18
|
+
remarkPrism
|
|
19
|
+
};
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
import { bundledLanguages, getHighlighter } from "shikiji";
|
|
2
|
+
import { visit } from "unist-util-visit";
|
|
3
|
+
const ASTRO_COLOR_REPLACEMENTS = {
|
|
4
|
+
"#000001": "var(--astro-code-color-text)",
|
|
5
|
+
"#000002": "var(--astro-code-color-background)",
|
|
6
|
+
"#000004": "var(--astro-code-token-constant)",
|
|
7
|
+
"#000005": "var(--astro-code-token-string)",
|
|
8
|
+
"#000006": "var(--astro-code-token-comment)",
|
|
9
|
+
"#000007": "var(--astro-code-token-keyword)",
|
|
10
|
+
"#000008": "var(--astro-code-token-parameter)",
|
|
11
|
+
"#000009": "var(--astro-code-token-function)",
|
|
12
|
+
"#000010": "var(--astro-code-token-string-expression)",
|
|
13
|
+
"#000011": "var(--astro-code-token-punctuation)",
|
|
14
|
+
"#000012": "var(--astro-code-token-link)"
|
|
15
|
+
};
|
|
16
|
+
const COLOR_REPLACEMENT_REGEX = new RegExp(
|
|
17
|
+
`(${Object.keys(ASTRO_COLOR_REPLACEMENTS).join("|")})`,
|
|
18
|
+
"g"
|
|
19
|
+
);
|
|
20
|
+
const highlighterCacheAsync = /* @__PURE__ */ new Map();
|
|
21
|
+
function remarkShiki({
|
|
22
|
+
langs = [],
|
|
23
|
+
theme = "github-dark",
|
|
24
|
+
experimentalThemes = {},
|
|
25
|
+
wrap = false
|
|
26
|
+
} = {}) {
|
|
27
|
+
const themes = experimentalThemes;
|
|
28
|
+
const cacheId = Object.values(themes).map((t) => typeof t === "string" ? t : t.name ?? "").join(",") + (typeof theme === "string" ? theme : theme.name ?? "") + langs.map((l) => l.name ?? l.id).join(",");
|
|
29
|
+
let highlighterAsync = highlighterCacheAsync.get(cacheId);
|
|
30
|
+
if (!highlighterAsync) {
|
|
31
|
+
highlighterAsync = getHighlighter({
|
|
32
|
+
langs: langs.length ? langs : Object.keys(bundledLanguages),
|
|
33
|
+
themes: Object.values(themes).length ? Object.values(themes) : [theme]
|
|
34
|
+
});
|
|
35
|
+
highlighterCacheAsync.set(cacheId, highlighterAsync);
|
|
36
|
+
}
|
|
37
|
+
return async (tree) => {
|
|
38
|
+
const highlighter = await highlighterAsync;
|
|
39
|
+
visit(tree, "code", (node) => {
|
|
40
|
+
let lang;
|
|
41
|
+
if (typeof node.lang === "string") {
|
|
42
|
+
const langExists = highlighter.getLoadedLanguages().includes(node.lang);
|
|
43
|
+
if (langExists) {
|
|
44
|
+
lang = node.lang;
|
|
45
|
+
} else {
|
|
46
|
+
console.warn(`The language "${node.lang}" doesn't exist, falling back to plaintext.`);
|
|
47
|
+
lang = "plaintext";
|
|
48
|
+
}
|
|
49
|
+
} else {
|
|
50
|
+
lang = "plaintext";
|
|
51
|
+
}
|
|
52
|
+
let themeOptions = Object.values(themes).length ? { themes } : { theme };
|
|
53
|
+
let html = highlighter.codeToHtml(node.value, { ...themeOptions, lang });
|
|
54
|
+
html = html.replace(/<pre class="(.*?)shiki(.*?)"/, `<pre class="$1astro-code$2"`);
|
|
55
|
+
if (node.lang === "diff") {
|
|
56
|
+
html = html.replace(
|
|
57
|
+
/<span class="line"><span style="(.*?)">([\+|\-])/g,
|
|
58
|
+
'<span class="line"><span style="$1"><span style="user-select: none;">$2</span>'
|
|
59
|
+
);
|
|
60
|
+
}
|
|
61
|
+
if (wrap === false) {
|
|
62
|
+
html = html.replace(/style="(.*?)"/, 'style="$1; overflow-x: auto;"');
|
|
63
|
+
} else if (wrap === true) {
|
|
64
|
+
html = html.replace(
|
|
65
|
+
/style="(.*?)"/,
|
|
66
|
+
'style="$1; overflow-x: auto; white-space: pre-wrap; word-wrap: break-word;"'
|
|
67
|
+
);
|
|
68
|
+
}
|
|
69
|
+
const themeName = typeof theme === "string" ? theme : theme.name;
|
|
70
|
+
if (themeName === "css-variables") {
|
|
71
|
+
html = html.replace(/style="(.*?)"/g, (m) => replaceCssVariables(m));
|
|
72
|
+
}
|
|
73
|
+
node.type = "html";
|
|
74
|
+
node.value = html;
|
|
75
|
+
node.children = [];
|
|
76
|
+
});
|
|
77
|
+
};
|
|
78
|
+
}
|
|
79
|
+
function replaceCssVariables(str) {
|
|
80
|
+
return str.replace(COLOR_REPLACEMENT_REGEX, (match) => ASTRO_COLOR_REPLACEMENTS[match] || match);
|
|
81
|
+
}
|
|
82
|
+
export {
|
|
83
|
+
remarkShiki
|
|
84
|
+
};
|
package/dist/types.d.ts
ADDED
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
import type * as hast from 'hast';
|
|
2
|
+
import type * as mdast from 'mdast';
|
|
3
|
+
import type { one as Handler, all as Handlers, Options as RemarkRehypeOptions } from 'remark-rehype';
|
|
4
|
+
import type { BuiltinTheme, LanguageRegistration, ThemeRegistration, ThemeRegistrationRaw } from 'shikiji';
|
|
5
|
+
import type * as unified from 'unified';
|
|
6
|
+
import type { VFile } from 'vfile';
|
|
7
|
+
export type { Node } from 'unist';
|
|
8
|
+
export type MarkdownAstroData = {
|
|
9
|
+
frontmatter: Record<string, any>;
|
|
10
|
+
};
|
|
11
|
+
export type RemarkPlugin<PluginParameters extends any[] = any[]> = unified.Plugin<PluginParameters, mdast.Root>;
|
|
12
|
+
export type RemarkPlugins = (string | [string, any] | RemarkPlugin | [RemarkPlugin, any])[];
|
|
13
|
+
export type RehypePlugin<PluginParameters extends any[] = any[]> = unified.Plugin<PluginParameters, hast.Root>;
|
|
14
|
+
export type RehypePlugins = (string | [string, any] | RehypePlugin | [RehypePlugin, any])[];
|
|
15
|
+
export type RemarkRehype = Omit<RemarkRehypeOptions, 'handlers' | 'unknownHandler'> & {
|
|
16
|
+
handlers?: typeof Handlers;
|
|
17
|
+
handler?: typeof Handler;
|
|
18
|
+
};
|
|
19
|
+
export interface ShikiConfig {
|
|
20
|
+
langs?: LanguageRegistration[];
|
|
21
|
+
theme?: BuiltinTheme | ThemeRegistration | ThemeRegistrationRaw;
|
|
22
|
+
experimentalThemes?: Record<string, BuiltinTheme | ThemeRegistration | ThemeRegistrationRaw>;
|
|
23
|
+
wrap?: boolean | null;
|
|
24
|
+
}
|
|
25
|
+
export interface AstroMarkdownOptions {
|
|
26
|
+
drafts?: boolean;
|
|
27
|
+
syntaxHighlight?: 'shiki' | 'prism' | false;
|
|
28
|
+
shikiConfig?: ShikiConfig;
|
|
29
|
+
remarkPlugins?: RemarkPlugins;
|
|
30
|
+
rehypePlugins?: RehypePlugins;
|
|
31
|
+
remarkRehype?: RemarkRehype;
|
|
32
|
+
gfm?: boolean;
|
|
33
|
+
smartypants?: boolean;
|
|
34
|
+
}
|
|
35
|
+
export interface ImageMetadata {
|
|
36
|
+
src: string;
|
|
37
|
+
width: number;
|
|
38
|
+
height: number;
|
|
39
|
+
type: string;
|
|
40
|
+
}
|
|
41
|
+
export interface MarkdownProcessor {
|
|
42
|
+
render: (content: string, opts?: MarkdownProcessorRenderOptions) => Promise<MarkdownProcessorRenderResult>;
|
|
43
|
+
}
|
|
44
|
+
export interface MarkdownProcessorRenderOptions {
|
|
45
|
+
/** Used for frontmatter injection plugins */
|
|
46
|
+
frontmatter?: Record<string, any>;
|
|
47
|
+
}
|
|
48
|
+
export interface MarkdownProcessorRenderResult {
|
|
49
|
+
code: string;
|
|
50
|
+
metadata: {
|
|
51
|
+
headings: MarkdownHeading[];
|
|
52
|
+
imagePaths: Set<string>;
|
|
53
|
+
frontmatter: Record<string, any>;
|
|
54
|
+
};
|
|
55
|
+
}
|
|
56
|
+
export interface MarkdownRenderingOptions extends AstroMarkdownOptions, MarkdownProcessorRenderOptions {
|
|
57
|
+
}
|
|
58
|
+
export interface MarkdownHeading {
|
|
59
|
+
depth: number;
|
|
60
|
+
slug: string;
|
|
61
|
+
text: string;
|
|
62
|
+
}
|
|
63
|
+
export interface MarkdownMetadata {
|
|
64
|
+
headings: MarkdownHeading[];
|
|
65
|
+
source: string;
|
|
66
|
+
html: string;
|
|
67
|
+
}
|
|
68
|
+
export interface MarkdownVFile extends VFile {
|
|
69
|
+
data: {
|
|
70
|
+
__astroHeadings?: MarkdownHeading[];
|
|
71
|
+
imagePaths?: Set<string>;
|
|
72
|
+
};
|
|
73
|
+
}
|
|
74
|
+
export interface MarkdownRenderingResult {
|
|
75
|
+
metadata: MarkdownMetadata;
|
|
76
|
+
vfile: MarkdownVFile;
|
|
77
|
+
code: string;
|
|
78
|
+
}
|
package/dist/types.js
ADDED
|
File without changes
|
package/package.json
ADDED
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@astrojs/markdown-remark",
|
|
3
|
+
"version": "0.0.0-assets-uint8array-20231109073138",
|
|
4
|
+
"type": "module",
|
|
5
|
+
"author": "withastro",
|
|
6
|
+
"license": "MIT",
|
|
7
|
+
"repository": {
|
|
8
|
+
"type": "git",
|
|
9
|
+
"url": "https://github.com/withastro/astro.git",
|
|
10
|
+
"directory": "packages/markdown/remark"
|
|
11
|
+
},
|
|
12
|
+
"bugs": "https://github.com/withastro/astro/issues",
|
|
13
|
+
"homepage": "https://astro.build",
|
|
14
|
+
"main": "./dist/index.js",
|
|
15
|
+
"exports": {
|
|
16
|
+
".": "./dist/index.js",
|
|
17
|
+
"./dist/internal.js": "./dist/internal.js"
|
|
18
|
+
},
|
|
19
|
+
"files": [
|
|
20
|
+
"dist"
|
|
21
|
+
],
|
|
22
|
+
"peerDependencies": {
|
|
23
|
+
"astro": "0.0.0-assets-uint8array-20231109073138"
|
|
24
|
+
},
|
|
25
|
+
"dependencies": {
|
|
26
|
+
"@astrojs/prism": "^3.0.0",
|
|
27
|
+
"github-slugger": "^2.0.0",
|
|
28
|
+
"import-meta-resolve": "^3.0.0",
|
|
29
|
+
"mdast-util-definitions": "^6.0.0",
|
|
30
|
+
"rehype-raw": "^6.1.1",
|
|
31
|
+
"rehype-stringify": "^9.0.4",
|
|
32
|
+
"remark-gfm": "^3.0.1",
|
|
33
|
+
"remark-parse": "^10.0.2",
|
|
34
|
+
"remark-rehype": "^10.1.0",
|
|
35
|
+
"remark-smartypants": "^2.0.0",
|
|
36
|
+
"shikiji": "^0.6.8",
|
|
37
|
+
"unified": "^10.1.2",
|
|
38
|
+
"unist-util-visit": "^4.1.2",
|
|
39
|
+
"vfile": "^5.3.7"
|
|
40
|
+
},
|
|
41
|
+
"devDependencies": {
|
|
42
|
+
"@types/chai": "^4.3.5",
|
|
43
|
+
"@types/estree": "^1.0.1",
|
|
44
|
+
"@types/hast": "^2.3.5",
|
|
45
|
+
"@types/mdast": "^3.0.12",
|
|
46
|
+
"@types/mocha": "^10.0.1",
|
|
47
|
+
"@types/unist": "^2.0.7",
|
|
48
|
+
"chai": "^4.3.7",
|
|
49
|
+
"mdast-util-mdx-expression": "^1.3.2",
|
|
50
|
+
"mocha": "^10.2.0",
|
|
51
|
+
"astro-scripts": "0.0.14"
|
|
52
|
+
},
|
|
53
|
+
"publishConfig": {
|
|
54
|
+
"provenance": true
|
|
55
|
+
},
|
|
56
|
+
"scripts": {
|
|
57
|
+
"prepublish": "pnpm build",
|
|
58
|
+
"build": "astro-scripts build \"src/**/*.ts\" && tsc -p tsconfig.json",
|
|
59
|
+
"build:ci": "astro-scripts build \"src/**/*.ts\"",
|
|
60
|
+
"postbuild": "astro-scripts copy \"src/**/*.js\"",
|
|
61
|
+
"dev": "astro-scripts dev \"src/**/*.ts\"",
|
|
62
|
+
"test": "mocha --exit --timeout 20000"
|
|
63
|
+
}
|
|
64
|
+
}
|