@nuxtjs/mdc 0.10.0 → 0.11.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.
package/dist/module.d.mts CHANGED
@@ -3,6 +3,7 @@ import { BundledLanguage, LanguageRegistration, BundledTheme, ThemeRegistrationA
3
3
  import { Options } from 'remark-rehype';
4
4
  import { R as RehypeHighlightOption, M as MdcConfig, a as MdcThemeOptions } from './shared/mdc.4762b8bc.mjs';
5
5
  export { A as Awaitable, b as HighlightResult, c as Highlighter, H as HighlighterOptions, d as defineConfig } from './shared/mdc.4762b8bc.mjs';
6
+ import { Options as Options$1 } from 'remark-stringify';
6
7
  import 'unified';
7
8
  import 'hast';
8
9
 
@@ -80,6 +81,14 @@ interface MDCParserResult {
80
81
  toc: Toc | undefined;
81
82
  }
82
83
 
84
+ interface MDCStringifyOptions {
85
+ plugins?: {
86
+ remarkStringify?: {
87
+ options?: Options$1;
88
+ };
89
+ };
90
+ }
91
+
83
92
  interface UnistPlugin {
84
93
  src?: string;
85
94
  options?: Record<string, any>;
@@ -515,6 +524,12 @@ interface Text extends Literal {
515
524
  */
516
525
  type TextData = Data;
517
526
 
527
+ interface MDCRenderOptions {
528
+ documentMeta: MDCData;
529
+ parentScope: any;
530
+ resolveComponent: (component: any) => any;
531
+ }
532
+
518
533
  declare const DefaultHighlightLangs: BundledLanguage[];
519
534
  declare const _default: _nuxt_schema.NuxtModule<ModuleOptions, ModuleOptions, false>;
520
535
 
@@ -546,4 +561,4 @@ declare module '@nuxt/schema' {
546
561
  }
547
562
  }
548
563
 
549
- export { type Comment, type CommentData, type Content, type Data, DefaultHighlightLangs, type Doctype, type DoctypeData, type Element, type ElementContent, type ElementContentMap, type ElementData, type Literal, type Literals, type MDCComment, type MDCData, type MDCElement, type MDCNode, type MDCParseOptions, type MDCParserResult, type MDCRoot, type MDCText, MdcConfig, MdcThemeOptions, type ModuleOptions, type Node, type Nodes, type Parent, type Parents, type Properties, RehypeHighlightOption, type RehypePlugin, type RemarkPlugin, type Root, type RootContent, type RootContentMap, type RootData, type Text, type TextData, type Toc, type TocLink, type UnistPlugin, _default as default };
564
+ export { type Comment, type CommentData, type Content, type Data, DefaultHighlightLangs, type Doctype, type DoctypeData, type Element, type ElementContent, type ElementContentMap, type ElementData, type Literal, type Literals, type MDCComment, type MDCData, type MDCElement, type MDCNode, type MDCParseOptions, type MDCParserResult, type MDCRenderOptions, type MDCRoot, type MDCStringifyOptions, type MDCText, MdcConfig, MdcThemeOptions, type ModuleOptions, type Node, type Nodes, type Parent, type Parents, type Properties, RehypeHighlightOption, type RehypePlugin, type RemarkPlugin, type Root, type RootContent, type RootContentMap, type RootData, type Text, type TextData, type Toc, type TocLink, type UnistPlugin, _default as default };
package/dist/module.d.ts CHANGED
@@ -3,6 +3,7 @@ import { BundledLanguage, LanguageRegistration, BundledTheme, ThemeRegistrationA
3
3
  import { Options } from 'remark-rehype';
4
4
  import { R as RehypeHighlightOption, M as MdcConfig, a as MdcThemeOptions } from './shared/mdc.4762b8bc.js';
5
5
  export { A as Awaitable, b as HighlightResult, c as Highlighter, H as HighlighterOptions, d as defineConfig } from './shared/mdc.4762b8bc.js';
6
+ import { Options as Options$1 } from 'remark-stringify';
6
7
  import 'unified';
7
8
  import 'hast';
8
9
 
@@ -80,6 +81,14 @@ interface MDCParserResult {
80
81
  toc: Toc | undefined;
81
82
  }
82
83
 
84
+ interface MDCStringifyOptions {
85
+ plugins?: {
86
+ remarkStringify?: {
87
+ options?: Options$1;
88
+ };
89
+ };
90
+ }
91
+
83
92
  interface UnistPlugin {
84
93
  src?: string;
85
94
  options?: Record<string, any>;
@@ -515,6 +524,12 @@ interface Text extends Literal {
515
524
  */
516
525
  type TextData = Data;
517
526
 
527
+ interface MDCRenderOptions {
528
+ documentMeta: MDCData;
529
+ parentScope: any;
530
+ resolveComponent: (component: any) => any;
531
+ }
532
+
518
533
  declare const DefaultHighlightLangs: BundledLanguage[];
519
534
  declare const _default: _nuxt_schema.NuxtModule<ModuleOptions, ModuleOptions, false>;
520
535
 
@@ -546,4 +561,4 @@ declare module '@nuxt/schema' {
546
561
  }
547
562
  }
548
563
 
549
- export { type Comment, type CommentData, type Content, type Data, DefaultHighlightLangs, type Doctype, type DoctypeData, type Element, type ElementContent, type ElementContentMap, type ElementData, type Literal, type Literals, type MDCComment, type MDCData, type MDCElement, type MDCNode, type MDCParseOptions, type MDCParserResult, type MDCRoot, type MDCText, MdcConfig, MdcThemeOptions, type ModuleOptions, type Node, type Nodes, type Parent, type Parents, type Properties, RehypeHighlightOption, type RehypePlugin, type RemarkPlugin, type Root, type RootContent, type RootContentMap, type RootData, type Text, type TextData, type Toc, type TocLink, type UnistPlugin, _default as default };
564
+ export { type Comment, type CommentData, type Content, type Data, DefaultHighlightLangs, type Doctype, type DoctypeData, type Element, type ElementContent, type ElementContentMap, type ElementData, type Literal, type Literals, type MDCComment, type MDCData, type MDCElement, type MDCNode, type MDCParseOptions, type MDCParserResult, type MDCRenderOptions, type MDCRoot, type MDCStringifyOptions, type MDCText, MdcConfig, MdcThemeOptions, type ModuleOptions, type Node, type Nodes, type Parent, type Parents, type Properties, RehypeHighlightOption, type RehypePlugin, type RemarkPlugin, type Root, type RootContent, type RootContentMap, type RootData, type Text, type TextData, type Toc, type TocLink, type UnistPlugin, _default as default };
package/dist/module.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@nuxtjs/mdc",
3
3
  "configKey": "mdc",
4
- "version": "0.10.0",
4
+ "version": "0.11.0",
5
5
  "builder": {
6
6
  "@nuxt/module-builder": "0.8.4",
7
7
  "unbuild": "2.0.0"
@@ -1,5 +1,5 @@
1
1
  <script>
2
- import { h, resolveComponent, reactive, watch, Text, Comment, defineAsyncComponent, defineComponent, toRaw, computed, getCurrentInstance } from "vue";
2
+ import { h, resolveComponent as vueResolveComponent, reactive, watch, Text, Comment, defineAsyncComponent, defineComponent, toRaw, computed, getCurrentInstance } from "vue";
3
3
  import destr from "destr";
4
4
  import { kebabCase, pascalCase } from "scule";
5
5
  import { find, html } from "property-information";
@@ -11,6 +11,7 @@ const rxOn = /^@|^v-on:/;
11
11
  const rxBind = /^:|^v-bind:/;
12
12
  const rxModel = /^v-model/;
13
13
  const nativeInputs = ["select", "textarea", "input"];
14
+ const specialParentTags = ["math", "svg"];
14
15
  const proseComponentMap = Object.fromEntries(["p", "a", "blockquote", "code", "pre", "code", "em", "h1", "h2", "h3", "h4", "h5", "h6", "hr", "img", "ul", "ol", "li", "strong", "table", "thead", "tbody", "td", "th", "tr", "script"].map((t) => [t, `prose-${t}`]));
15
16
  export default defineComponent({
16
17
  name: "MDCRenderer",
@@ -105,20 +106,25 @@ export default defineComponent({
105
106
  return null;
106
107
  }
107
108
  const meta = { ...data, tags, $route: route, runtimeData, updateRuntimeData };
108
- const component = tag !== false ? resolveVueComponent(tag || meta.component?.name || meta.component || "div") : void 0;
109
+ const component = tag !== false ? resolveComponentInstance(tag || meta.component?.name || meta.component || "div") : void 0;
109
110
  return component ? h(component, { ...meta.component?.props, class: ctx.class, ...this.$attrs, key: contentKey }, { default: defaultSlotRenderer }) : defaultSlotRenderer?.();
110
111
  function defaultSlotRenderer() {
112
+ const defaultSlot = _renderSlots(body, h, { documentMeta: meta, parentScope: meta, resolveComponent: resolveComponentInstance });
113
+ if (!defaultSlot?.default) {
114
+ return null;
115
+ }
111
116
  if (unwrap) {
112
117
  return flatUnwrap(
113
- renderSlots(body, h, meta, meta).default(),
118
+ defaultSlot.default(),
114
119
  typeof unwrap === "string" ? unwrap.split(" ") : ["*"]
115
120
  );
116
121
  }
117
- return renderSlots(body, h, meta, meta).default();
122
+ return defaultSlot.default();
118
123
  }
119
124
  }
120
125
  });
121
- function renderNode(node, h2, documentMeta, parentScope = {}) {
126
+ function _renderNode(node, h2, options) {
127
+ const { documentMeta, parentScope, resolveComponent } = options;
122
128
  if (node.type === "text") {
123
129
  return h2(Text, node.value);
124
130
  }
@@ -130,7 +136,8 @@ function renderNode(node, h2, documentMeta, parentScope = {}) {
130
136
  if (node.tag === "binding") {
131
137
  return renderBinding(node, h2, documentMeta, parentScope);
132
138
  }
133
- const component = resolveVueComponent(renderTag);
139
+ const _resolveComponent = isUnresolvableTag(renderTag) ? (component2) => component2 : resolveComponent;
140
+ const component = _resolveComponent(renderTag);
134
141
  if (typeof component === "object") {
135
142
  component.tag = originalTag;
136
143
  }
@@ -138,32 +145,19 @@ function renderNode(node, h2, documentMeta, parentScope = {}) {
138
145
  return h2(
139
146
  component,
140
147
  props,
141
- renderSlots(node, h2, documentMeta, { ...parentScope, ...props })
142
- );
143
- }
144
- function renderBinding(node, h2, documentMeta, parentScope = {}) {
145
- const data = {
146
- ...documentMeta.runtimeData,
147
- ...parentScope,
148
- $document: documentMeta,
149
- $doc: documentMeta
150
- };
151
- const splitter = /\.|\[(\d+)\]/;
152
- const keys = node.props?.value.trim().split(splitter).filter(Boolean);
153
- const value = keys.reduce((data2, key) => {
154
- if (data2 && key in data2) {
155
- if (typeof data2[key] === "function") {
156
- return data2[key]();
157
- } else {
158
- return data2[key];
148
+ _renderSlots(
149
+ node,
150
+ h2,
151
+ {
152
+ documentMeta,
153
+ parentScope: { ...parentScope, ...props },
154
+ resolveComponent: _resolveComponent
159
155
  }
160
- }
161
- return void 0;
162
- }, data);
163
- const defaultValue = node.props?.defaultValue;
164
- return h2(Text, value ?? defaultValue ?? "");
156
+ )
157
+ );
165
158
  }
166
- function renderSlots(node, h2, documentMeta, parentProps) {
159
+ function _renderSlots(node, h2, options) {
160
+ const { documentMeta, parentScope, resolveComponent } = options;
167
161
  const children = node.children || [];
168
162
  const slotNodes = children.reduce((data, node2) => {
169
163
  if (!isTemplate(node2)) {
@@ -186,7 +180,15 @@ function renderSlots(node, h2, documentMeta, parentProps) {
186
180
  }
187
181
  slots2[name] = (data = {}) => {
188
182
  const scopedProps = pick(data, Object.keys(props || {}));
189
- let vNodes = children2.map((child) => renderNode(child, h2, documentMeta, { ...parentProps, ...scopedProps }));
183
+ let vNodes = children2.map((child) => _renderNode(
184
+ child,
185
+ h2,
186
+ {
187
+ documentMeta,
188
+ parentScope: { ...parentScope, ...scopedProps },
189
+ resolveComponent
190
+ }
191
+ ));
190
192
  if (props?.unwrap) {
191
193
  vNodes = flatUnwrap(vNodes, props.unwrap);
192
194
  }
@@ -196,6 +198,28 @@ function renderSlots(node, h2, documentMeta, parentProps) {
196
198
  }, {});
197
199
  return slots;
198
200
  }
201
+ function renderBinding(node, h2, documentMeta, parentScope = {}) {
202
+ const data = {
203
+ ...documentMeta.runtimeData,
204
+ ...parentScope,
205
+ $document: documentMeta,
206
+ $doc: documentMeta
207
+ };
208
+ const splitter = /\.|\[(\d+)\]/;
209
+ const keys = node.props?.value.trim().split(splitter).filter(Boolean);
210
+ const value = keys.reduce((data2, key) => {
211
+ if (data2 && key in data2) {
212
+ if (typeof data2[key] === "function") {
213
+ return data2[key]();
214
+ } else {
215
+ return data2[key];
216
+ }
217
+ }
218
+ return void 0;
219
+ }, data);
220
+ const defaultValue = node.props?.defaultValue;
221
+ return h2(Text, value ?? defaultValue ?? "");
222
+ }
199
223
  function propsToData(node, documentMeta) {
200
224
  const { tag = "", props = {} } = node;
201
225
  return Object.keys(props).reduce(function(data, key) {
@@ -250,12 +274,12 @@ function propsToDataRxBind(key, value, data, documentMeta) {
250
274
  data[key] = evalInContext(value, documentMeta);
251
275
  return data;
252
276
  }
253
- const resolveVueComponent = (component) => {
277
+ const resolveComponentInstance = (component) => {
254
278
  if (typeof component === "string") {
255
279
  if (htmlTags.includes(component)) {
256
280
  return component;
257
281
  }
258
- const _component = resolveComponent(pascalCase(component), false);
282
+ const _component = vueResolveComponent(pascalCase(component), false);
259
283
  if (!component || _component?.name === "AsyncComponentWrapper") {
260
284
  return _component;
261
285
  }
@@ -287,6 +311,9 @@ function getSlotName(node) {
287
311
  function isTemplate(node) {
288
312
  return node.tag === "template";
289
313
  }
314
+ function isUnresolvableTag(tag) {
315
+ return specialParentTags.includes(tag);
316
+ }
290
317
  function mergeTextNodes(nodes) {
291
318
  const mergedNodes = [];
292
319
  for (const node of nodes) {
@@ -308,7 +335,7 @@ async function resolveContentComponents(body, meta) {
308
335
  if (c?.render || c?.ssrRender || c?.__ssrInlineRender) {
309
336
  return;
310
337
  }
311
- const resolvedComponent = resolveVueComponent(c);
338
+ const resolvedComponent = resolveComponentInstance(c);
312
339
  if (resolvedComponent?.__asyncLoader && !resolvedComponent.__asyncResolved) {
313
340
  await resolvedComponent.__asyncLoader();
314
341
  }
@@ -319,6 +346,9 @@ async function resolveContentComponents(body, meta) {
319
346
  return [];
320
347
  }
321
348
  const renderTag = findMappedTag(node, documentMeta.tags);
349
+ if (isUnresolvableTag(renderTag)) {
350
+ return [];
351
+ }
322
352
  const components2 = [];
323
353
  if (node.type !== "root" && !htmlTags.includes(renderTag)) {
324
354
  components2.push(renderTag);
@@ -1,4 +1,5 @@
1
- export { parseMarkdown, createMarkdownParser } from './parser/index.js';
1
+ export { parseMarkdown, createMarkdownParser, createParseProcessor } from './parser/index.js';
2
+ export { stringifyMarkdown, createMarkdownStringifier, createStringifyProcessor } from './stringify/index.js';
2
3
  export { rehypeHighlight } from './highlighter/rehype.js';
3
4
  export { createShikiHighlighter } from './highlighter/shiki.js';
4
5
  export * from './utils/node.js';
@@ -1,4 +1,5 @@
1
- export { parseMarkdown, createMarkdownParser } from "./parser/index.js";
1
+ export { parseMarkdown, createMarkdownParser, createParseProcessor } from "./parser/index.js";
2
+ export { stringifyMarkdown, createMarkdownStringifier, createStringifyProcessor } from "./stringify/index.js";
2
3
  export { rehypeHighlight } from "./highlighter/rehype.js";
3
4
  export { createShikiHighlighter } from "./highlighter/shiki.js";
4
5
  export * from "./utils/node.js";
@@ -1,6 +1,6 @@
1
1
  import type { Options as VFileOptions } from 'vfile';
2
2
  import type { MDCParseOptions, MDCParserResult, MDCRoot } from '@nuxtjs/mdc';
3
- export declare const createProcessor: (inlineOptions?: MDCParseOptions) => Promise<import("unified").Processor<undefined, undefined, undefined, undefined, undefined>>;
3
+ export declare const createParseProcessor: (inlineOptions?: MDCParseOptions) => Promise<import("unified").Processor<undefined, undefined, undefined, undefined, undefined>>;
4
4
  export declare const createMarkdownParser: (inlineOptions?: MDCParseOptions) => Promise<(md: string, { fileOptions }?: {
5
5
  fileOptions?: VFileOptions;
6
6
  }) => Promise<MDCParserResult>>;
@@ -10,7 +10,7 @@ import { generateToc } from "./toc.js";
10
10
  import { compileHast } from "./compiler.js";
11
11
  let moduleOptions;
12
12
  let generatedMdcConfigs;
13
- export const createProcessor = async (inlineOptions = {}) => {
13
+ export const createParseProcessor = async (inlineOptions = {}) => {
14
14
  if (!moduleOptions) {
15
15
  moduleOptions = await import(
16
16
  "#mdc-imports"
@@ -70,7 +70,7 @@ export const createProcessor = async (inlineOptions = {}) => {
70
70
  return processor;
71
71
  };
72
72
  export const createMarkdownParser = async (inlineOptions = {}) => {
73
- const processor = await createProcessor(inlineOptions);
73
+ const processor = await createParseProcessor(inlineOptions);
74
74
  return async function parse(md, { fileOptions } = {}) {
75
75
  const { content, data: frontmatter } = await parseFrontMatter(md);
76
76
  const processedFile = await processor.process({ ...fileOptions, value: content, data: frontmatter });
@@ -0,0 +1,5 @@
1
+ import { type Processor } from 'unified';
2
+ import type { MDCStringifyOptions, MDCRoot } from '@nuxtjs/mdc';
3
+ export declare function createStringifyProcessor(options?: MDCStringifyOptions): Processor<undefined, import("hast").Root, import("unist").Node, import("mdast").Root, string>;
4
+ export declare function createMarkdownStringifier(options?: MDCStringifyOptions): (value: any, data?: Record<string, any>) => Promise<string>;
5
+ export declare function stringifyMarkdown(MDCAst: MDCRoot, data: Record<string, any>, options?: MDCStringifyOptions): Promise<string | null>;
@@ -0,0 +1,36 @@
1
+ import { unified } from "unified";
2
+ import gfm from "remark-gfm";
3
+ import mdc, { stringifyFrontMatter } from "remark-mdc";
4
+ import stringify from "remark-stringify";
5
+ import { mdcRemark } from "./mdc-remark.js";
6
+ export function createStringifyProcessor(options = {}) {
7
+ return unified().use(function jsonParser() {
8
+ this.parser = function(root) {
9
+ return JSON.parse(root);
10
+ };
11
+ }).use(mdcRemark).use(gfm).use(mdc).use(stringify, {
12
+ bullet: "-",
13
+ emphasis: "_",
14
+ rule: "-",
15
+ listItemIndent: "one",
16
+ fence: "`",
17
+ fences: true,
18
+ ...options?.plugins?.remarkStringify?.options
19
+ });
20
+ }
21
+ export function createMarkdownStringifier(options = {}) {
22
+ const processor = createStringifyProcessor(options);
23
+ async function stringify2(value, data = {}) {
24
+ const result = await processor.process({ value: JSON.stringify(value) });
25
+ if (Object.keys(data).length) {
26
+ return stringifyFrontMatter(data, result.value);
27
+ }
28
+ return result.value;
29
+ }
30
+ return stringify2;
31
+ }
32
+ export async function stringifyMarkdown(MDCAst, data, options = {}) {
33
+ const processor = createMarkdownStringifier(options);
34
+ if (!MDCAst) return null;
35
+ return await processor(MDCAst, data);
36
+ }
@@ -0,0 +1,8 @@
1
+ import type { Root as HastRoot } from 'hast';
2
+ import type { Options as ToMdastOptions } from 'hast-util-to-mdast';
3
+ import type { Root as MDastRoot } from 'mdast';
4
+ import type { VFile } from 'vfile';
5
+ interface Options extends ToMdastOptions {
6
+ }
7
+ export declare function mdcRemark(options?: Options | undefined | null): (node: HastRoot, _file: VFile) => MDastRoot;
8
+ export {};
@@ -0,0 +1,253 @@
1
+ import { defaultHandlers, toMdast } from "hast-util-to-mdast";
2
+ import { nodeTextContent } from "@nuxtjs/mdc/runtime/utils/node";
3
+ import { hasProtocol } from "ufo";
4
+ import { toHtml } from "hast-util-to-html";
5
+ import { visit } from "unist-util-visit";
6
+ import { format } from "hast-util-format";
7
+ import { computeHighlightRanges } from "./utils.js";
8
+ const mdcRemarkElementType = "mdc-element";
9
+ const own = {}.hasOwnProperty;
10
+ export function mdcRemark(options) {
11
+ return function(node, _file) {
12
+ const tree = preProcessElementNodes(node);
13
+ const mdast = toMdast(tree, {
14
+ /**
15
+ * Default to true in rehype-remark
16
+ * @see https://github.com/rehypejs/rehype-remark/blob/main/lib/index.js#L37ckages/remark/lib/index.js#L100
17
+ */
18
+ document: true,
19
+ ...options,
20
+ handlers: {
21
+ ...mdcRemarkHandlers,
22
+ ...options?.handlers
23
+ },
24
+ nodeHandlers: {
25
+ ...mdcRemarkNodeHandlers,
26
+ ...options?.nodeHandlers
27
+ }
28
+ });
29
+ return mdast;
30
+ };
31
+ }
32
+ function preProcessElementNodes(node) {
33
+ if (node.type === "element") {
34
+ if (node.children?.length && (node.children || []).every((child) => child.tag === "template")) {
35
+ node.children = node.children.flatMap((child) => {
36
+ if (typeof child.props?.["v-slot:default"] !== "undefined" && Object.keys(child.props).length === 1) {
37
+ return child.children || [];
38
+ }
39
+ return child;
40
+ });
41
+ }
42
+ const result = {
43
+ type: mdcRemarkElementType,
44
+ tagName: node.tag,
45
+ properties: node.props,
46
+ children: (node.children || []).map(preProcessElementNodes)
47
+ };
48
+ if (!node.children?.length) {
49
+ delete result.children;
50
+ }
51
+ return result;
52
+ }
53
+ if (node?.children) {
54
+ return {
55
+ ...node,
56
+ children: (node.children || []).map(preProcessElementNodes)
57
+ };
58
+ }
59
+ return node;
60
+ }
61
+ const mdcRemarkNodeHandlers = {
62
+ [mdcRemarkElementType]: (state, node, parent) => {
63
+ if (node.properties && node.properties.dataMdast === "ignore") {
64
+ return;
65
+ }
66
+ if (own.call(state.handlers, node.tagName)) {
67
+ return state.handlers[node.tagName](state, node, parent) || void 0;
68
+ }
69
+ if ("value" in node && typeof node.value === "string") {
70
+ const result = { type: "text", value: node.value };
71
+ state.patch(node, result);
72
+ return result;
73
+ }
74
+ const isInlineElement = (parent?.children || []).some((child) => child.type === "text") || ["p", "li"].includes(parent?.tagName);
75
+ if (isInlineElement) {
76
+ return {
77
+ type: "textComponent",
78
+ name: node.tagName,
79
+ attributes: node.properties,
80
+ children: state.all(node)
81
+ };
82
+ }
83
+ return {
84
+ type: "containerComponent",
85
+ name: node.tagName,
86
+ attributes: node.properties,
87
+ children: state.all(node)
88
+ };
89
+ }
90
+ };
91
+ const mdcRemarkHandlers = {
92
+ template: (state, node) => {
93
+ const vSlot = Object.keys(node.properties || {}).find((prop) => prop?.startsWith("v-slot:"))?.replace("v-slot:", "") || "default";
94
+ const attributes = Object.fromEntries(Object.entries(node.properties || {}).filter(([key]) => !key.startsWith("v-slot:")));
95
+ return {
96
+ type: "componentContainerSection",
97
+ name: vSlot,
98
+ attributes,
99
+ children: state.toFlow(state.all(node))
100
+ };
101
+ },
102
+ div: (state, node) => {
103
+ return {
104
+ type: "containerComponent",
105
+ name: "div",
106
+ attributes: node.properties,
107
+ children: state.toFlow(state.all(node))
108
+ };
109
+ },
110
+ code: (state, node) => {
111
+ const attributes = { ...node.properties };
112
+ if ("style" in attributes && !attributes.style) {
113
+ delete attributes.style;
114
+ }
115
+ if ("class" in attributes) {
116
+ attributes.className = String(attributes.class).split(" ").filter(Boolean);
117
+ delete attributes.class;
118
+ }
119
+ if (Array.isArray(attributes.className)) {
120
+ attributes.className = attributes.className.filter((name) => !name.startsWith("language-"));
121
+ if (Array.isArray(attributes.className) && !attributes.className.length) {
122
+ delete attributes.className;
123
+ }
124
+ }
125
+ if (attributes.language) {
126
+ attributes.lang = attributes.language;
127
+ delete attributes.language;
128
+ }
129
+ const result = { type: "inlineCode", value: nodeTextContent(node), attributes };
130
+ state.patch(node, result);
131
+ return result;
132
+ },
133
+ pre: (_state, node) => {
134
+ const meta = [
135
+ node.properties.filename ? `[${String(node.properties.filename).replace(/\]/g, "\\]")}]` : "",
136
+ node.properties.highlights?.length ? `{${computeHighlightRanges(node.properties.highlights)}}` : "",
137
+ node.properties.meta
138
+ ].filter(Boolean).join(" ");
139
+ const value = String(node.properties.code || "").replace(/\n$/, "");
140
+ return {
141
+ type: "code",
142
+ value,
143
+ lang: node.properties.language,
144
+ meta
145
+ };
146
+ },
147
+ binding: (state, node) => {
148
+ return {
149
+ type: "textComponent",
150
+ name: "binding",
151
+ attributes: node.properties,
152
+ children: state.toFlow(state.all(node))
153
+ };
154
+ },
155
+ span: (state, node) => {
156
+ const result = {
157
+ type: "textComponent",
158
+ name: "span",
159
+ attributes: node.properties,
160
+ children: state.all(node)
161
+ };
162
+ state.patch(node, result);
163
+ return result;
164
+ },
165
+ video: (state, node) => {
166
+ return {
167
+ type: "textComponent",
168
+ name: "video",
169
+ attributes: node.properties,
170
+ children: state.toFlow(state.all(node))
171
+ };
172
+ },
173
+ "nuxt-img": (state, node) => {
174
+ return {
175
+ type: "textComponent",
176
+ name: "nuxt-img",
177
+ attributes: node.properties,
178
+ children: state.toFlow(state.all(node))
179
+ };
180
+ },
181
+ "nuxt-picture": (state, node) => {
182
+ return {
183
+ type: "textComponent",
184
+ name: "nuxt-picture",
185
+ attributes: node.properties,
186
+ children: state.toFlow(state.all(node))
187
+ };
188
+ },
189
+ table: (state, node) => {
190
+ visit(node, (node2) => {
191
+ if (node2.type === "rehype-element") {
192
+ node2.type = "element";
193
+ }
194
+ });
195
+ if (Object.keys(node.properties).length) {
196
+ format({ type: "root", children: [node] });
197
+ return {
198
+ type: "html",
199
+ value: toHtml(node)
200
+ };
201
+ }
202
+ return defaultHandlers.table(state, node);
203
+ },
204
+ img: (state, node) => {
205
+ const { src, title, alt, ...attributes } = node.properties || {};
206
+ const result = {
207
+ type: "image",
208
+ url: state.resolve(String(src || "") || null),
209
+ title: title ? String(title) : null,
210
+ alt: alt ? String(alt) : "",
211
+ attributes
212
+ };
213
+ state.patch(node, result);
214
+ return result;
215
+ },
216
+ em: (state, node) => {
217
+ const result = { type: "emphasis", children: state.all(node), attributes: node.properties };
218
+ state.patch(node, result);
219
+ return result;
220
+ },
221
+ strong: (state, node) => {
222
+ const result = { type: "strong", children: state.all(node), attributes: node.properties };
223
+ state.patch(node, result);
224
+ return result;
225
+ },
226
+ a(state, node) {
227
+ const { href, title, ...attributes } = node.properties || {};
228
+ if (hasProtocol(String(href || ""))) {
229
+ if (attributes.target === "_blank") {
230
+ delete attributes.target;
231
+ }
232
+ if (["nofollow,noopener,noreferrer"].includes(String(attributes.rel))) {
233
+ delete attributes.rel;
234
+ }
235
+ }
236
+ const result = {
237
+ type: "link",
238
+ url: state.resolve(String(href || "") || null),
239
+ title: title ? String(title) : null,
240
+ children: state.all(node),
241
+ attributes
242
+ };
243
+ state.patch(node, result);
244
+ return result;
245
+ },
246
+ br(state, node) {
247
+ return {
248
+ type: "textComponent",
249
+ name: "br",
250
+ attributes: node.properties
251
+ };
252
+ }
253
+ };
@@ -0,0 +1 @@
1
+ export declare function computeHighlightRanges(input: string[] | string): string;
@@ -0,0 +1,16 @@
1
+ export function computeHighlightRanges(input) {
2
+ const numbers = Array.isArray(input) ? input.map(Number) : input.split(",").map(Number);
3
+ const ranges = [];
4
+ let start = numbers[0];
5
+ for (let i = 1; i <= numbers.length; i++) {
6
+ if (numbers[i] !== numbers[i - 1] + 1) {
7
+ if (start === numbers[i - 1]) {
8
+ ranges.push(`${start}`);
9
+ } else {
10
+ ranges.push(`${start}-${numbers[i - 1]}`);
11
+ }
12
+ start = numbers[i];
13
+ }
14
+ }
15
+ return ranges.join(",");
16
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@nuxtjs/mdc",
3
- "version": "0.10.0",
3
+ "version": "0.11.0",
4
4
  "description": "Nuxt MDC module",
5
5
  "repository": "nuxt-modules/mdc",
6
6
  "license": "MIT",
@@ -72,16 +72,18 @@
72
72
  },
73
73
  "dependencies": {
74
74
  "@nuxt/kit": "^3.14.1592",
75
- "@shikijs/transformers": "^1.24.0",
75
+ "@shikijs/transformers": "^1.24.1",
76
76
  "@types/hast": "^3.0.4",
77
77
  "@types/mdast": "^4.0.4",
78
78
  "@vue/compiler-core": "^3.5.13",
79
79
  "consola": "^3.2.3",
80
- "debug": "^4.3.7",
80
+ "debug": "^4.4.0",
81
81
  "defu": "^6.1.4",
82
82
  "destr": "^2.0.3",
83
83
  "detab": "^3.0.2",
84
84
  "github-slugger": "^2.0.0",
85
+ "hast-util-format": "^1.1.0",
86
+ "hast-util-to-mdast": "^10.1.1",
85
87
  "hast-util-to-string": "^3.0.1",
86
88
  "mdast-util-to-hast": "^13.2.0",
87
89
  "micromark-util-sanitize-uri": "^2.0.1",
@@ -90,7 +92,9 @@
90
92
  "pathe": "^1.1.2",
91
93
  "property-information": "^6.5.0",
92
94
  "rehype-external-links": "^3.0.0",
95
+ "rehype-minify-whitespace": "^6.0.2",
93
96
  "rehype-raw": "^7.0.0",
97
+ "rehype-remark": "^10.0.0",
94
98
  "rehype-slug": "^6.0.0",
95
99
  "rehype-sort-attribute-values": "^5.0.1",
96
100
  "rehype-sort-attributes": "^5.0.1",
@@ -99,8 +103,9 @@
99
103
  "remark-mdc": "^3.5.0",
100
104
  "remark-parse": "^11.0.0",
101
105
  "remark-rehype": "^11.1.1",
106
+ "remark-stringify": "^11.0.0",
102
107
  "scule": "^1.3.0",
103
- "shiki": "^1.24.0",
108
+ "shiki": "^1.24.1",
104
109
  "ufo": "^1.5.4",
105
110
  "unified": "^11.0.5",
106
111
  "unist-builder": "^4.0.0",
@@ -113,8 +118,8 @@
113
118
  "@nuxt/eslint-config": "^0.7.2",
114
119
  "@nuxt/module-builder": "^0.8.4",
115
120
  "@nuxt/schema": "^3.14.1592",
116
- "@nuxt/test-utils": "^3.14.4",
117
- "@nuxt/ui": "^2.19.2",
121
+ "@nuxt/test-utils": "^3.15.1",
122
+ "@nuxt/ui": "^2.20.0",
118
123
  "@nuxtjs/mdc": "link:.",
119
124
  "@types/node": "^22.10.1",
120
125
  "changelogen": "^0.5.7",
@@ -123,14 +128,13 @@
123
128
  "rehype": "^13.0.2",
124
129
  "release-it": "^17.10.0",
125
130
  "typescript": "5.6.3",
126
- "vitest": "^2.1.7",
131
+ "vitest": "^2.1.8",
127
132
  "vue-tsc": "^2.1.10"
128
133
  },
129
134
  "resolutions": {
130
- "@nuxtjs/mdc": "workspace:*",
131
- "remark-mdc": "npm:remark-mdc-edge@latest"
135
+ "@nuxtjs/mdc": "workspace:*"
132
136
  },
133
- "packageManager": "pnpm@9.14.4",
137
+ "packageManager": "pnpm@9.15.0",
134
138
  "release-it": {
135
139
  "git": {
136
140
  "commitMessage": "chore(release): release v${version}"