@nuxtjs/mdc 0.1.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.
Files changed (109) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +64 -0
  3. package/dist/module.cjs +5 -0
  4. package/dist/module.d.mts +55 -0
  5. package/dist/module.d.ts +55 -0
  6. package/dist/module.json +5 -0
  7. package/dist/module.mjs +174 -0
  8. package/dist/runtime/components/MDC.vue +36 -0
  9. package/dist/runtime/components/MDCRenderer.vue +293 -0
  10. package/dist/runtime/components/MDCRenderer.vue.d.ts +92 -0
  11. package/dist/runtime/components/MDCSlot.vue +60 -0
  12. package/dist/runtime/components/MDCSlot.vue.d.ts +5 -0
  13. package/dist/runtime/components/prose/ProseA.vue +22 -0
  14. package/dist/runtime/components/prose/ProseBlockquote.vue +5 -0
  15. package/dist/runtime/components/prose/ProseCode.vue +3 -0
  16. package/dist/runtime/components/prose/ProseEm.vue +5 -0
  17. package/dist/runtime/components/prose/ProseH1.vue +20 -0
  18. package/dist/runtime/components/prose/ProseH2.vue +20 -0
  19. package/dist/runtime/components/prose/ProseH3.vue +20 -0
  20. package/dist/runtime/components/prose/ProseH4.vue +20 -0
  21. package/dist/runtime/components/prose/ProseH5.vue +20 -0
  22. package/dist/runtime/components/prose/ProseH6.vue +20 -0
  23. package/dist/runtime/components/prose/ProseHr.vue +3 -0
  24. package/dist/runtime/components/prose/ProseImg.vue +42 -0
  25. package/dist/runtime/components/prose/ProseLi.vue +3 -0
  26. package/dist/runtime/components/prose/ProseOl.vue +5 -0
  27. package/dist/runtime/components/prose/ProseP.vue +3 -0
  28. package/dist/runtime/components/prose/ProsePre.vue +39 -0
  29. package/dist/runtime/components/prose/ProseStrong.vue +5 -0
  30. package/dist/runtime/components/prose/ProseTable.vue +5 -0
  31. package/dist/runtime/components/prose/ProseTbody.vue +5 -0
  32. package/dist/runtime/components/prose/ProseTd.vue +5 -0
  33. package/dist/runtime/components/prose/ProseTh.vue +5 -0
  34. package/dist/runtime/components/prose/ProseThead.vue +5 -0
  35. package/dist/runtime/components/prose/ProseTr.vue +5 -0
  36. package/dist/runtime/components/prose/ProseUl.vue +5 -0
  37. package/dist/runtime/index.d.ts +3 -0
  38. package/dist/runtime/index.mjs +3 -0
  39. package/dist/runtime/parser/compiler.d.ts +1 -0
  40. package/dist/runtime/parser/compiler.mjs +78 -0
  41. package/dist/runtime/parser/handlers/code.d.ts +5 -0
  42. package/dist/runtime/parser/handlers/code.mjs +31 -0
  43. package/dist/runtime/parser/handlers/containerComponent.d.ts +10 -0
  44. package/dist/runtime/parser/handlers/containerComponent.mjs +15 -0
  45. package/dist/runtime/parser/handlers/emphasis.d.ts +6 -0
  46. package/dist/runtime/parser/handlers/emphasis.mjs +10 -0
  47. package/dist/runtime/parser/handlers/html.d.ts +3 -0
  48. package/dist/runtime/parser/handlers/html.mjs +14 -0
  49. package/dist/runtime/parser/handlers/image.d.ts +6 -0
  50. package/dist/runtime/parser/handlers/image.mjs +13 -0
  51. package/dist/runtime/parser/handlers/index.d.ts +22 -0
  52. package/dist/runtime/parser/handlers/index.mjs +22 -0
  53. package/dist/runtime/parser/handlers/inlineCode.d.ts +6 -0
  54. package/dist/runtime/parser/handlers/inlineCode.mjs +12 -0
  55. package/dist/runtime/parser/handlers/link.d.ts +6 -0
  56. package/dist/runtime/parser/handlers/link.mjs +18 -0
  57. package/dist/runtime/parser/handlers/list.d.ts +4 -0
  58. package/dist/runtime/parser/handlers/list.mjs +26 -0
  59. package/dist/runtime/parser/handlers/paragraph.d.ts +4 -0
  60. package/dist/runtime/parser/handlers/paragraph.mjs +19 -0
  61. package/dist/runtime/parser/handlers/strong.d.ts +6 -0
  62. package/dist/runtime/parser/handlers/strong.mjs +10 -0
  63. package/dist/runtime/parser/handlers/utils.d.ts +19 -0
  64. package/dist/runtime/parser/handlers/utils.mjs +33 -0
  65. package/dist/runtime/parser/index.d.ts +11 -0
  66. package/dist/runtime/parser/index.mjs +60 -0
  67. package/dist/runtime/parser/options.d.ts +2 -0
  68. package/dist/runtime/parser/options.mjs +50 -0
  69. package/dist/runtime/parser/shiki.d.ts +8 -0
  70. package/dist/runtime/parser/shiki.mjs +55 -0
  71. package/dist/runtime/parser/toc.d.ts +3 -0
  72. package/dist/runtime/parser/toc.mjs +59 -0
  73. package/dist/runtime/parser/utils/html-tags-list.d.ts +2 -0
  74. package/dist/runtime/parser/utils/html-tags-list.mjs +119 -0
  75. package/dist/runtime/parser/utils/plugins.d.ts +3 -0
  76. package/dist/runtime/parser/utils/plugins.mjs +10 -0
  77. package/dist/runtime/parser/utils/props.d.ts +5 -0
  78. package/dist/runtime/parser/utils/props.mjs +33 -0
  79. package/dist/runtime/shiki/event-handler.d.ts +8 -0
  80. package/dist/runtime/shiki/event-handler.mjs +15 -0
  81. package/dist/runtime/shiki/highlighter.d.ts +25 -0
  82. package/dist/runtime/shiki/highlighter.mjs +298 -0
  83. package/dist/runtime/shiki/mdc.tmLanguage.d.ts +323 -0
  84. package/dist/runtime/shiki/mdc.tmLanguage.mjs +582 -0
  85. package/dist/runtime/shiki/types.d.ts +32 -0
  86. package/dist/runtime/shiki/types.mjs +0 -0
  87. package/dist/runtime/types/hast.d.ts +255 -0
  88. package/dist/runtime/types/hast.mjs +0 -0
  89. package/dist/runtime/types/index.d.ts +3 -0
  90. package/dist/runtime/types/index.mjs +3 -0
  91. package/dist/runtime/types/parser.d.ts +30 -0
  92. package/dist/runtime/types/parser.mjs +0 -0
  93. package/dist/runtime/types/toc.d.ts +12 -0
  94. package/dist/runtime/types/toc.mjs +0 -0
  95. package/dist/runtime/types/tree.d.ts +17 -0
  96. package/dist/runtime/types/tree.mjs +0 -0
  97. package/dist/runtime/types/unist.d.ts +107 -0
  98. package/dist/runtime/types/unist.mjs +0 -0
  99. package/dist/runtime/utils/ast.d.ts +6 -0
  100. package/dist/runtime/utils/ast.mjs +29 -0
  101. package/dist/runtime/utils/node.d.ts +37 -0
  102. package/dist/runtime/utils/node.mjs +75 -0
  103. package/dist/runtime/utils/slot.d.ts +3 -0
  104. package/dist/runtime/utils/slot.mjs +8 -0
  105. package/dist/runtime/utils/ssrSlot.d.ts +1 -0
  106. package/dist/runtime/utils/ssrSlot.mjs +8 -0
  107. package/dist/types.d.mts +7 -0
  108. package/dist/types.d.ts +7 -0
  109. package/package.json +99 -0
@@ -0,0 +1,50 @@
1
+ import handlers from "./handlers/index.mjs";
2
+ import remarkEmoji from "remark-emoji";
3
+ import remarkGFM from "remark-gfm";
4
+ import rehypeExternalLinks from "rehype-external-links";
5
+ import rehypeSortAttributeValues from "rehype-sort-attribute-values";
6
+ import rehypeSortAttributes from "rehype-sort-attributes";
7
+ import rehypeRaw from "rehype-raw";
8
+ import { remarkPlugins, rehypePlugins, highlight } from "#mdc-imports";
9
+ export const defaults = {
10
+ remark: {
11
+ plugins: {
12
+ "remark-emoji": {
13
+ instance: remarkEmoji
14
+ },
15
+ "remark-gfm": {
16
+ instance: remarkGFM
17
+ },
18
+ ...remarkPlugins
19
+ }
20
+ },
21
+ rehype: {
22
+ options: {
23
+ handlers,
24
+ allowDangerousHtml: true
25
+ },
26
+ plugins: {
27
+ "rehype-external-links": {
28
+ instance: rehypeExternalLinks
29
+ },
30
+ "rehype-sort-attribute-values": {
31
+ instance: rehypeSortAttributeValues
32
+ },
33
+ "rehype-sort-attributes": {
34
+ instance: rehypeSortAttributes
35
+ },
36
+ "rehype-raw": {
37
+ instance: rehypeRaw,
38
+ options: {
39
+ passThrough: ["element"]
40
+ }
41
+ },
42
+ ...rehypePlugins
43
+ }
44
+ },
45
+ highlight,
46
+ toc: {
47
+ searchDepth: 2,
48
+ depth: 2
49
+ }
50
+ };
@@ -0,0 +1,8 @@
1
+ import type { Root } from '../types/hast';
2
+ import type { Highlighter, Theme } from '../shiki/types';
3
+ interface RehypeShikiOption {
4
+ theme?: Theme;
5
+ highlighter?: Highlighter;
6
+ }
7
+ export declare function rehypeShiki(opts?: RehypeShikiOption): (tree: Root) => Promise<void>;
8
+ export {};
@@ -0,0 +1,55 @@
1
+ import { visit } from "unist-util-visit";
2
+ import { toString } from "hast-util-to-string";
3
+ import { defu } from "defu";
4
+ const defaults = {
5
+ theme: {
6
+ default: "github-dark",
7
+ dark: "github-light"
8
+ },
9
+ highlighter: (code, lang, theme) => {
10
+ return $fetch("/api/_mdc/highlight", {
11
+ params: {
12
+ code,
13
+ lang,
14
+ theme: JSON.stringify(theme)
15
+ }
16
+ });
17
+ }
18
+ };
19
+ export function rehypeShiki(opts = {}) {
20
+ const options = defu(opts, defaults);
21
+ return async (tree) => {
22
+ const tasks = [];
23
+ const styles = [];
24
+ visit(
25
+ tree,
26
+ (node) => node.tagName === "pre" && !!node.properties?.language,
27
+ (node) => {
28
+ const _node = node;
29
+ const task = options.highlighter(toString(node), _node.properties.language, options.theme).then(({ tree: tree2, className, style }) => {
30
+ _node.properties.className = ((_node.properties.className || "") + " " + className).trim();
31
+ if (_node.children[0]?.tagName === "code") {
32
+ _node.children[0].children = tree2;
33
+ } else {
34
+ _node.children = tree2;
35
+ }
36
+ styles.push(style);
37
+ });
38
+ tasks.push(task);
39
+ }
40
+ );
41
+ if (tasks.length) {
42
+ await Promise.all(tasks);
43
+ tree.children.push({
44
+ type: "element",
45
+ tagName: "style",
46
+ children: [{ type: "text", value: cleanCSS(styles.join("")) }],
47
+ properties: {}
48
+ });
49
+ }
50
+ };
51
+ }
52
+ const cleanCSS = (css) => {
53
+ const styles = css.split("}").filter((s) => Boolean(s.trim())).map((s) => s.trim() + "}");
54
+ return Array.from(new Set(styles)).join("");
55
+ };
@@ -0,0 +1,3 @@
1
+ import { MDCNode, Toc, MDCElement, MDCRoot } from '../types';
2
+ export declare function generateFlatToc(body: MDCNode, options: Toc): Toc;
3
+ export declare function generateToc(body: MDCElement | MDCRoot, options: Toc): Toc;
@@ -0,0 +1,59 @@
1
+ import { flattenNode, flattenNodeText } from "../utils/ast.mjs";
2
+ const TOC_TAGS = ["h2", "h3", "h4", "h5", "h6"];
3
+ const TOC_TAGS_DEPTH = TOC_TAGS.reduce((tags, tag) => {
4
+ tags[tag] = Number(tag.charAt(tag.length - 1));
5
+ return tags;
6
+ }, {});
7
+ const getHeaderDepth = (node) => TOC_TAGS_DEPTH[node.tag];
8
+ const getTocTags = (depth) => {
9
+ if (depth < 1 || depth > 5) {
10
+ console.log(`\`toc.depth\` is set to ${depth}. It should be a number between 1 and 5. `);
11
+ depth = 1;
12
+ }
13
+ return TOC_TAGS.slice(0, depth);
14
+ };
15
+ function nestHeaders(headers) {
16
+ if (headers.length <= 1) {
17
+ return headers;
18
+ }
19
+ const toc = [];
20
+ let parent;
21
+ headers.forEach((header) => {
22
+ if (!parent || header.depth <= parent.depth) {
23
+ header.children = [];
24
+ parent = header;
25
+ toc.push(header);
26
+ } else {
27
+ parent.children.push(header);
28
+ }
29
+ });
30
+ toc.forEach((header) => {
31
+ if (header.children?.length) {
32
+ header.children = nestHeaders(header.children);
33
+ } else {
34
+ delete header.children;
35
+ }
36
+ });
37
+ return toc;
38
+ }
39
+ export function generateFlatToc(body, options) {
40
+ const { searchDepth, depth, title = "" } = options;
41
+ const tags = getTocTags(depth);
42
+ const headers = flattenNode(body, searchDepth).filter((node) => tags.includes(node.tag || ""));
43
+ const links = headers.map((node) => ({
44
+ id: node.props?.id,
45
+ depth: getHeaderDepth(node),
46
+ text: flattenNodeText(node)
47
+ }));
48
+ return {
49
+ title,
50
+ searchDepth,
51
+ depth,
52
+ links
53
+ };
54
+ }
55
+ export function generateToc(body, options) {
56
+ const toc = generateFlatToc(body, options);
57
+ toc.links = nestHeaders(toc.links);
58
+ return toc;
59
+ }
@@ -0,0 +1,2 @@
1
+ declare const _default: string[];
2
+ export default _default;
@@ -0,0 +1,119 @@
1
+ export default [
2
+ "a",
3
+ "abbr",
4
+ "address",
5
+ "area",
6
+ "article",
7
+ "aside",
8
+ "audio",
9
+ "b",
10
+ "base",
11
+ "bdi",
12
+ "bdo",
13
+ "blockquote",
14
+ "body",
15
+ "br",
16
+ "button",
17
+ "canvas",
18
+ "caption",
19
+ "cite",
20
+ "code",
21
+ "col",
22
+ "colgroup",
23
+ "data",
24
+ "datalist",
25
+ "dd",
26
+ "del",
27
+ "details",
28
+ "dfn",
29
+ "dialog",
30
+ "div",
31
+ "dl",
32
+ "dt",
33
+ "em",
34
+ "embed",
35
+ "fieldset",
36
+ "figcaption",
37
+ "figure",
38
+ "footer",
39
+ "form",
40
+ "h1",
41
+ "h2",
42
+ "h3",
43
+ "h4",
44
+ "h5",
45
+ "h6",
46
+ "head",
47
+ "header",
48
+ "hgroup",
49
+ "hr",
50
+ "html",
51
+ "i",
52
+ "iframe",
53
+ "img",
54
+ "input",
55
+ "ins",
56
+ "kbd",
57
+ "label",
58
+ "legend",
59
+ "li",
60
+ "link",
61
+ "main",
62
+ "map",
63
+ "mark",
64
+ "math",
65
+ "menu",
66
+ "menuitem",
67
+ "meta",
68
+ "meter",
69
+ "nav",
70
+ "noscript",
71
+ "object",
72
+ "ol",
73
+ "optgroup",
74
+ "option",
75
+ "output",
76
+ "p",
77
+ "param",
78
+ "picture",
79
+ "pre",
80
+ "progress",
81
+ "q",
82
+ "rb",
83
+ "rp",
84
+ "rt",
85
+ "rtc",
86
+ "ruby",
87
+ "s",
88
+ "samp",
89
+ "script",
90
+ "section",
91
+ "select",
92
+ "slot",
93
+ "small",
94
+ "source",
95
+ "span",
96
+ "strong",
97
+ "style",
98
+ "sub",
99
+ "summary",
100
+ "sup",
101
+ "svg",
102
+ "table",
103
+ "tbody",
104
+ "td",
105
+ "template",
106
+ "textarea",
107
+ "tfoot",
108
+ "th",
109
+ "thead",
110
+ "time",
111
+ "title",
112
+ "tr",
113
+ "track",
114
+ "u",
115
+ "ul",
116
+ "var",
117
+ "video",
118
+ "wbr"
119
+ ];
@@ -0,0 +1,3 @@
1
+ import { Processor } from 'remark-rehype/lib';
2
+ import { MDCParseOptions } from '../../types';
3
+ export declare const useProcessorPlugins: (processor: Processor, plugins?: Exclude<MDCParseOptions['rehype'] | MDCParseOptions['remark'], undefined>['plugins']) => Promise<void>;
@@ -0,0 +1,10 @@
1
+ export const useProcessorPlugins = async (processor, plugins = {}) => {
2
+ const toUse = Object.entries(plugins).filter((p) => p[1] !== false);
3
+ for (const plugin of toUse) {
4
+ const instance = plugin[1].instance || await import(
5
+ /* @vite-ignore */
6
+ plugin[0]
7
+ ).then((m) => m.default || m);
8
+ processor.use(instance, plugin[1].options);
9
+ }
10
+ };
@@ -0,0 +1,5 @@
1
+ export declare const unsafeLinkPrefix: string[];
2
+ export declare const validateProp: (attribute: string, value: string) => boolean;
3
+ export declare const validateProps: (props?: Record<string, any>) => {
4
+ [k: string]: any;
5
+ };
@@ -0,0 +1,33 @@
1
+ export const unsafeLinkPrefix = [
2
+ "javascript:",
3
+ "data:text/html",
4
+ "vbscript:",
5
+ "data:text/javascript",
6
+ "data:text/vbscript",
7
+ "data:text/css",
8
+ "data:text/plain",
9
+ "data:text/xml"
10
+ ];
11
+ export const validateProp = (attribute, value) => {
12
+ if (attribute.startsWith("on")) {
13
+ return false;
14
+ }
15
+ if (attribute === "href" || attribute === "src") {
16
+ return !unsafeLinkPrefix.some((prefix) => value.toLowerCase().startsWith(prefix));
17
+ }
18
+ return true;
19
+ };
20
+ export const validateProps = (props) => {
21
+ if (!props) {
22
+ return {};
23
+ }
24
+ return Object.fromEntries(
25
+ Object.entries(props).filter(([name, value]) => {
26
+ const isValid = validateProp(name, value);
27
+ if (!isValid) {
28
+ console.warn(`[@nuxtjs/mdc] removing unsafe attribute: ${name}="${value}"`);
29
+ }
30
+ return isValid;
31
+ })
32
+ );
33
+ };
@@ -0,0 +1,8 @@
1
+ import type { TokenStyleMap } from './types';
2
+ declare const _default: import("h3").EventHandler<import("h3").EventHandlerRequest, Promise<{
3
+ tree: import("../types/hast").Element[];
4
+ className: string;
5
+ style: string;
6
+ styleMap: TokenStyleMap;
7
+ }>>;
8
+ export default _default;
@@ -0,0 +1,15 @@
1
+ import { eventHandler, getQuery } from "h3";
2
+ import { useShikiHighlighter } from "./highlighter.mjs";
3
+ export default eventHandler(async (event) => {
4
+ const { code, lang, theme: themeString } = getQuery(event);
5
+ const theme = JSON.parse(themeString);
6
+ const shikiHighlighter = useShikiHighlighter({});
7
+ const styleMap = {};
8
+ const { tree, className } = await shikiHighlighter.getHighlightedAST(code, lang, theme, { styleMap });
9
+ return {
10
+ tree,
11
+ className,
12
+ style: shikiHighlighter.generateStyles(styleMap),
13
+ styleMap
14
+ };
15
+ });
@@ -0,0 +1,25 @@
1
+ import { Lang } from 'shiki-es';
2
+ import type { HighlighterOptions, Theme, TokenStyleMap } from './types';
3
+ import type { Element } from '../types/hast';
4
+ export declare const useShikiHighlighter: (opts?: any) => {
5
+ getHighlightedTokens: (code: string, lang: Lang, theme: Theme) => Promise<{
6
+ code: string;
7
+ lang: Lang;
8
+ theme: {
9
+ [k: string]: import("shiki-es").IShikiTheme;
10
+ };
11
+ tokens: {
12
+ content: string;
13
+ }[][];
14
+ }>;
15
+ getHighlightedAST: (code: string, lang: Lang, theme: Theme, opts?: Partial<HighlighterOptions>) => Promise<{
16
+ tree: Element[];
17
+ className: string;
18
+ }>;
19
+ getHighlightedCode: (code: string, lang: Lang, theme: Theme, opts?: Partial<HighlighterOptions>) => Promise<{
20
+ code: string;
21
+ className: string;
22
+ styles: string;
23
+ }>;
24
+ generateStyles: (styleMap: TokenStyleMap) => string;
25
+ };