feature: vor und nachteile

This commit is contained in:
Hikyu
2026-05-31 13:54:31 +02:00
parent 552a947a1c
commit e3dad17446
23270 changed files with 3024794 additions and 200 deletions
+21
View File
@@ -0,0 +1,21 @@
MIT License
Copyright (c) 2022 Anthony Fu <https://github.com/antfu>
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:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
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.
+69
View File
@@ -0,0 +1,69 @@
# markdown-it-mdc
[![npm version][npm-version-src]][npm-version-href]
[![npm downloads][npm-downloads-src]][npm-downloads-href]
[![bundle][bundle-src]][bundle-href]
[![JSDocs][jsdocs-src]][jsdocs-href]
[![License][license-src]][license-href]
[MDC (Markdown Components)](https://content.nuxtjs.org/guide/writing/mdc) for [`markdown-it`](https://github.com/markdown-it/markdown-it).
Use [VS Code MDC Extension](https://marketplace.visualstudio.com/items?itemName=Nuxt.mdc) for IDE support.
## Usage
```bash
npm i markdown-it markdown-it-mdc
```
```ts
import MarkdownIt from 'markdown-it'
import pluginMdc from 'markdown-it-mdc'
const md = new MarkdownIt()
.use(pluginMdc)
const result = md.render(`
# Hello
Hello **World** with :my-component{.text-red name="foo"}!
`)
```
## Features
This plugin implements all the syntaxes documented in [MDC Syntax](https://content.nuxtjs.org/guide/writing/mdc). We are still testing behavior compatibility in detail before reaching `v0.1.0`.
- [x] [Block Component](https://content.nuxtjs.org/guide/writing/mdc#block-components)
- [x] [Nesting](https://content.nuxtjs.org/guide/writing/mdc#nesting)
- [x] [YAML Props](https://content.nuxtjs.org/guide/writing/mdc#yaml-props)
- [x] [Slots](https://content.nuxtjs.org/guide/writing/mdc#slots)
- [x] [Inline Components](https://content.nuxtjs.org/guide/writing/mdc#inline-components)
- [x] [Inline Props](https://content.nuxtjs.org/guide/writing/mdc#props)
- [x] [Span](https://content.nuxtjs.org/guide/writing/mdc#span-text)
- ~~Frontmatter~~. Frontmatter is not built-in in this plugin, we recommend using [`@mdit-vue/plugin-frontmatter`](https://github.com/mdit-vue/mdit-vue/tree/main/packages/plugin-frontmatter) instead.
## Sponsors
<p align="center">
<a href="https://cdn.jsdelivr.net/gh/antfu/static/sponsors.svg">
<img src='https://cdn.jsdelivr.net/gh/antfu/static/sponsors.svg'/>
</a>
</p>
## License
[MIT](./LICENSE) License © 2022 [Anthony Fu](https://github.com/antfu)
<!-- Badges -->
[npm-version-src]: https://img.shields.io/npm/v/markdown-it-mdc?style=flat&colorA=080f12&colorB=1fa669
[npm-version-href]: https://npmjs.com/package/markdown-it-mdc
[npm-downloads-src]: https://img.shields.io/npm/dm/markdown-it-mdc?style=flat&colorA=080f12&colorB=1fa669
[npm-downloads-href]: https://npmjs.com/package/markdown-it-mdc
[bundle-src]: https://img.shields.io/bundlephobia/minzip/markdown-it-mdc?style=flat&colorA=080f12&colorB=1fa669&label=minzip
[bundle-href]: https://bundlephobia.com/result?p=markdown-it-mdc
[license-src]: https://img.shields.io/github/license/nuxt-content/markdown-it-mdc.svg?style=flat&colorA=080f12&colorB=1fa669
[license-href]: https://github.com/nuxt-content/markdown-it-mdc/blob/main/LICENSE
[jsdocs-src]: https://img.shields.io/badge/jsdocs-reference-080f12?style=flat&colorA=080f12&colorB=1fa669
[jsdocs-href]: https://www.jsdocs.io/package/markdown-it-mdc
+41
View File
@@ -0,0 +1,41 @@
import MarkdownIt from 'markdown-it';
interface MarkdownItMdcOptions {
/**
* Options for toggling each syntax feature.
*/
syntax?: {
/**
* Enable block component syntax.
*
* @see https://content.nuxtjs.org/guide/writing/mdc#block-components
* @default true
*/
blockComponent?: boolean;
/**
* Enable inline props syntax.
*
* @see https://content.nuxtjs.org/guide/writing/mdc#inline-props
* @default true
*/
inlineProps?: boolean;
/**
* Enable inline span syntax.
*
* @see https://content.nuxtjs.org/guide/writing/mdc#inline-span
* @default true
*/
inlineSpan?: boolean;
/**
* Enable inline component syntax.
*
* @see https://content.nuxtjs.org/guide/writing/mdc#inline-component
* @default true
*/
inlineComponent?: boolean;
};
}
declare const MarkdownItMdc: MarkdownIt.PluginWithOptions<MarkdownItMdcOptions>;
export { MarkdownItMdc as default };
export type { MarkdownItMdcOptions };
+41
View File
@@ -0,0 +1,41 @@
import MarkdownIt from 'markdown-it';
interface MarkdownItMdcOptions {
/**
* Options for toggling each syntax feature.
*/
syntax?: {
/**
* Enable block component syntax.
*
* @see https://content.nuxtjs.org/guide/writing/mdc#block-components
* @default true
*/
blockComponent?: boolean;
/**
* Enable inline props syntax.
*
* @see https://content.nuxtjs.org/guide/writing/mdc#inline-props
* @default true
*/
inlineProps?: boolean;
/**
* Enable inline span syntax.
*
* @see https://content.nuxtjs.org/guide/writing/mdc#inline-span
* @default true
*/
inlineSpan?: boolean;
/**
* Enable inline component syntax.
*
* @see https://content.nuxtjs.org/guide/writing/mdc#inline-component
* @default true
*/
inlineComponent?: boolean;
};
}
declare const MarkdownItMdc: MarkdownIt.PluginWithOptions<MarkdownItMdcOptions>;
export { MarkdownItMdc as default };
export type { MarkdownItMdcOptions };
+725
View File
@@ -0,0 +1,725 @@
import { parse } from 'yaml';
import TokenClass from 'markdown-it/lib/token.mjs';
const NUMBER_CHAR_RE = /\d/;
const STR_SPLITTERS = ["-", "_", "/", "."];
function isUppercase(char = "") {
if (NUMBER_CHAR_RE.test(char)) {
return void 0;
}
return char !== char.toLowerCase();
}
function splitByCase(str, separators) {
const splitters = STR_SPLITTERS;
const parts = [];
if (!str || typeof str !== "string") {
return parts;
}
let buff = "";
let previousUpper;
let previousSplitter;
for (const char of str) {
const isSplitter = splitters.includes(char);
if (isSplitter === true) {
parts.push(buff);
buff = "";
previousUpper = void 0;
continue;
}
const isUpper = isUppercase(char);
if (previousSplitter === false) {
if (previousUpper === false && isUpper === true) {
parts.push(buff);
buff = char;
previousUpper = isUpper;
continue;
}
if (previousUpper === true && isUpper === false && buff.length > 1) {
const lastChar = buff.at(-1);
parts.push(buff.slice(0, Math.max(0, buff.length - 1)));
buff = lastChar + char;
previousUpper = isUpper;
continue;
}
}
buff += char;
previousUpper = isUpper;
previousSplitter = isSplitter;
}
parts.push(buff);
return parts;
}
function kebabCase(str, joiner) {
return str ? (Array.isArray(str) ? str : splitByCase(str)).map((p) => p.toLowerCase()).join("-") : "";
}
function parseBracketContent(str, startIndex) {
if (str[startIndex] !== "[")
return null;
let index = startIndex + 1;
while (index < str.length) {
if (str[index] === "\\" && index + 1 < str.length) {
index += 2;
continue;
}
if (str[index] === "]") {
const content = str.slice(startIndex + 1, index);
return { content, endIndex: index + 1 };
}
index += 1;
}
return null;
}
const bracketPairs = {
"[": "]",
"{": "}",
"(": ")"
};
const quotePairs = {
"'": "'",
'"': '"',
"`": "`"
};
function searchProps(content, index = 0) {
if (content[index] !== "{")
throw new Error(`Invalid props, expected \`{\` but got '${content[index]}'`);
const props = [];
if (content[index + 1] === "{")
return void 0;
index += 1;
while (index < content.length) {
if (content[index] === "\\") {
index += 2;
} else if (content[index] === "}") {
index += 1;
break;
} else if (content[index] === " ") {
index += 1;
} else if (content[index] === ".") {
index += 1;
props.push([
"class",
searchUntil(" #.}")
]);
} else if (content[index] === "#") {
index += 1;
props.push([
"id",
searchUntil(" #.}")
]);
} else {
const start = index;
while (index < content.length) {
index += 1;
if (" }=".includes(content[index]))
break;
}
const char = content[index];
if (start !== index) {
const key = content.slice(start, index).trim();
if (char === "=") {
index += 1;
props.push([
key,
searchValue()
]);
} else {
props.push([
key,
"true"
]);
}
}
}
}
function searchUntil(str) {
const start = index;
while (index < content.length) {
index += 1;
if (content[index] === "\\")
index += 2;
if (str.includes(content[index]))
break;
}
return content.slice(start, index);
}
function searchValue() {
const start = index;
if (content[index] in bracketPairs) {
searchBracket(bracketPairs[content[index]]);
index += 1;
return content.slice(start, index);
} else if (content[index] in quotePairs) {
searchString(quotePairs[content[index]]);
index += 1;
return content.slice(start, index);
} else {
return searchUntil(" }");
}
}
function searchBracket(end) {
while (index < content.length) {
index++;
if (content[index] in quotePairs)
searchString(quotePairs[content[index]]);
else if (content[index] in bracketPairs)
searchBracket(bracketPairs[content[index]]);
else if (content[index] === end)
return;
}
}
function searchString(end) {
return searchUntil(end);
}
props.forEach((v) => {
if (v[1].match(/^(['"`]).*\1$/))
v[1] = v[1].slice(1, -1);
});
return {
props,
index
};
}
const RE_BLOCK_NAME = /^[a-z$][$\w.-]*/i;
function parseBlockParams(str) {
str = str.trim();
if (!str)
return { name: "" };
const name = str.match(RE_BLOCK_NAME)?.[0];
if (!name)
throw new Error(`Invalid block params: ${str}`);
let remaining = str.slice(name.length).trim();
let content;
let props;
let unparsedRemaining;
if (remaining.startsWith("[")) {
const result2 = parseBracketContent(remaining, 0);
if (result2) {
content = result2.content;
remaining = remaining.slice(result2.endIndex).trim();
}
}
if (remaining.startsWith("{")) {
const propsResult = searchProps(remaining, 0);
if (propsResult) {
props = propsResult.props;
const afterProps = remaining.slice(propsResult.index).trim();
if (afterProps) {
unparsedRemaining = afterProps;
}
}
} else if (remaining) {
unparsedRemaining = remaining;
}
const result = {
name: kebabCase(name)
};
if (content !== void 0) {
result.content = content;
}
if (props !== void 0) {
result.props = props;
}
if (unparsedRemaining) {
result.remaining = unparsedRemaining;
}
return result;
}
const MarkdownItMdcBlock = (md) => {
const min_markers = 2;
const marker_str = ":";
const marker_char = marker_str.charCodeAt(0);
md.block.ruler.before(
"fence",
"mdc_block_shorthand",
// eslint-disable-next-line prefer-arrow-callback
function mdc_block_shorthand(state, startLine, endLine, silent) {
const line = state.src.slice(state.bMarks[startLine] + state.tShift[startLine], state.eMarks[startLine]);
if (!line.match(/^:\w/))
return false;
const parsed = parseBlockParams(line.slice(1));
const {
name,
content,
props,
remaining
} = parsed;
if (remaining) {
return false;
}
state.lineMax = startLine + 1;
if (!silent) {
if (content !== void 0) {
const tokenOpen = state.push("mdc_block_shorthand", name, 1);
props?.forEach(([key, value]) => {
if (key === "class")
tokenOpen.attrJoin(key, value);
else
tokenOpen.attrSet(key, value);
});
const inline = state.push("inline", "", 0);
inline.content = "";
const text = new state.Token("text", "", 0);
text.content = content;
inline.children = [text];
state.push("mdc_block_shorthand", name, -1);
} else {
const token = state.push("mdc_block_shorthand", name, 0);
props?.forEach(([key, value]) => {
if (key === "class")
token.attrJoin(key, value);
else
token.attrSet(key, value);
});
}
}
state.line = startLine + 1;
return true;
}
);
md.block.ruler.before(
"fence",
"mdc_block",
// eslint-disable-next-line prefer-arrow-callback
function mdc_block(state, startLine, endLine, silent) {
let pos;
let nextLine;
let auto_closed = false;
let start = state.bMarks[startLine] + state.tShift[startLine];
let max = state.eMarks[startLine];
const indent = state.sCount[startLine];
let inCodeFence = false;
let codeFenceCharCode = 0;
let codeFenceCount = 0;
let nestingDepth = 0;
if (state.src[start] !== ":")
return false;
for (pos = start + 1; pos <= max; pos++) {
if (marker_str !== state.src[pos])
break;
}
const marker_count = Math.floor(pos - start);
if (marker_count < min_markers)
return false;
const markup = state.src.slice(start, pos);
const params = parseBlockParams(state.src.slice(pos, max));
if (!params.name)
return false;
if (silent)
return true;
nextLine = startLine;
for (; ; ) {
nextLine++;
if (nextLine >= endLine) {
break;
}
start = state.bMarks[nextLine] + state.tShift[nextLine];
max = state.eMarks[nextLine];
if (start < max && state.sCount[nextLine] < state.blkIndent) {
break;
}
const lineCharCode = state.src.charCodeAt(start);
if (inCodeFence) {
if (lineCharCode === codeFenceCharCode) {
let fencePos = start + 1;
while (fencePos < max && state.src.charCodeAt(fencePos) === codeFenceCharCode)
fencePos++;
if (fencePos - start >= codeFenceCount) {
const afterFence = state.skipSpaces(fencePos);
if (afterFence >= max)
inCodeFence = false;
}
}
continue;
}
if (lineCharCode === 96 || lineCharCode === 126) {
let fencePos = start + 1;
while (fencePos < max && state.src.charCodeAt(fencePos) === lineCharCode)
fencePos++;
if (fencePos - start >= 3) {
inCodeFence = true;
codeFenceCharCode = lineCharCode;
codeFenceCount = fencePos - start;
continue;
}
}
if (marker_char !== lineCharCode)
continue;
for (pos = start + 1; pos <= max; pos++) {
if (marker_str !== state.src[pos])
break;
}
if (pos - start !== marker_count)
continue;
pos = state.skipSpaces(pos);
if (pos < max) {
nestingDepth++;
continue;
}
if (nestingDepth > 0) {
nestingDepth--;
continue;
}
auto_closed = true;
break;
}
const old_parent = state.parentType;
const old_line_max = state.lineMax;
state.parentType = "mdc_block";
state.lineMax = nextLine;
const tokenOpen = state.push("mdc_block_open", params.name, 1);
tokenOpen.markup = markup;
tokenOpen.block = true;
tokenOpen.info = params.name;
tokenOpen.map = [startLine, nextLine];
if (params.props) {
params.props?.forEach(([key, value]) => {
if (key === "class")
tokenOpen.attrJoin(key, value);
else
tokenOpen.attrSet(key, value);
});
}
const blkIndent = state.blkIndent;
state.blkIndent = indent;
state.env.mdcBlockTokens ||= [];
state.env.mdcBlockTokens.unshift(tokenOpen);
state.md.block.tokenize(state, startLine + 1, nextLine);
state.blkIndent = blkIndent;
state.env.mdcBlockTokens.shift(tokenOpen);
const tokenClose = state.push("mdc_block_close", params.name, -1);
tokenClose.map = [startLine, nextLine];
tokenClose.markup = state.src.slice(start, pos);
tokenClose.block = true;
state.tokens.slice(
state.tokens.indexOf(tokenOpen) + 1,
state.tokens.indexOf(tokenClose)
).filter((i) => i.level === tokenOpen.level + 1).forEach((i, _, arr) => {
if (arr.length <= 2 && i.tag === "p")
i.hidden = true;
});
state.parentType = old_parent;
state.lineMax = old_line_max;
state.line = nextLine + (auto_closed ? 1 : 0);
return true;
},
{
alt: ["paragraph", "reference", "blockquote", "list"]
}
);
md.block.ruler.after(
"code",
"mdc_block_yaml",
// eslint-disable-next-line prefer-arrow-callback
function mdc_block_yaml(state, startLine, endLine, silent) {
if (!state.env.mdcBlockTokens?.length)
return false;
const start = state.bMarks[startLine] + state.tShift[startLine];
const end = state.eMarks[startLine];
if (state.src.slice(start, end) !== "---")
return false;
let lineEnd = startLine + 1;
let found = false;
while (lineEnd < endLine) {
const line = state.src.slice(state.bMarks[lineEnd] + state.tShift[startLine], state.eMarks[lineEnd]);
if (line === "---") {
found = true;
break;
}
lineEnd += 1;
}
if (!found)
return false;
if (!silent) {
const yaml = state.src.slice(state.bMarks[startLine + 1], state.eMarks[lineEnd - 1]);
const data = parse(yaml);
const token = state.env.mdcBlockTokens[0];
Object.entries(data || {}).forEach(([key, value]) => {
if (key === "class")
token.attrJoin(key, value);
else
token.attrSet(key, typeof value === "string" ? value : JSON.stringify(value));
});
}
state.line = lineEnd + 1;
state.lineMax = lineEnd + 1;
return true;
}
);
md.block.ruler.after(
"code",
"mdc_block_slots",
// eslint-disable-next-line prefer-arrow-callback
function mdc_block(state, startLine, endLine, silent) {
if (!state.env.mdcBlockTokens?.length)
return false;
const start = state.bMarks[startLine] + state.tShift[startLine];
if (!(state.src[start] === "#" && state.src[start + 1] !== " "))
return false;
const line = state.src.slice(start, state.eMarks[startLine]);
const {
name,
props
} = parseBlockParams(line.slice(1));
let lineEnd = startLine + 1;
while (lineEnd < endLine) {
const line2 = state.src.slice(state.bMarks[lineEnd] + state.tShift[startLine], state.eMarks[lineEnd]);
if (line2.match(/^#(\w)+/) || line2.startsWith("::"))
break;
lineEnd += 1;
}
if (silent) {
state.line = lineEnd;
state.lineMax = lineEnd;
return true;
}
state.lineMax = startLine + 1;
const slot = state.push("mdc_block_slot", "template", 1);
slot.attrSet(`#${name}`, "");
props?.forEach(([key, value]) => {
if (key === "class")
slot.attrJoin(key, value);
else
slot.attrSet(key, value);
});
state.line = startLine + 1;
state.lineMax = lineEnd;
state.md.block.tokenize(state, startLine + 1, lineEnd);
state.push("mdc_block_slot", "template", -1);
state.line = lineEnd;
state.lineMax = lineEnd;
return true;
}
);
};
const ALLOWED_PREV_CHARS = /* @__PURE__ */ new Set([" ", " ", "\n", "*", "_", "["]);
const MarkdownItInlineComponent = (md) => {
md.inline.ruler.after("entity", "mdc_inline_component", (state, silent) => {
const start = state.pos;
const char = state.src[start];
if (char !== ":")
return false;
const prevChar = state.src[start - 1];
if (start > 0 && !ALLOWED_PREV_CHARS.has(prevChar))
return false;
let index = start + 1;
let nameEnd = -1;
let content;
while (index < state.src.length) {
const char2 = state.src[index];
if (char2 === "[") {
nameEnd = index;
const result = parseBracketContent(state.src, index);
if (result) {
content = result.content;
index = result.endIndex;
}
break;
}
if (!/[\w$\-]/.test(char2))
break;
index += 1;
}
if (nameEnd === -1)
nameEnd = index;
if (nameEnd <= start + 1)
return false;
state.pos = index;
if (silent)
return true;
const name = state.src.slice(start + 1, nameEnd);
if (content !== void 0) {
state.push("mdc_inline_component", name, 1);
const text = state.push("text", "", 0);
text.content = content;
state.push("mdc_inline_component", name, -1);
} else {
state.push("mdc_inline_component", name, 0);
}
return true;
});
};
const MarkdownItInlineProps = (md) => {
md.inline.ruler.after("entity", "mdc_inline_props", (state, silent) => {
const start = state.pos;
const char = state.src[start];
if (char !== "{")
return false;
if (state.src[start + 1] === "{" || state.src[start - 1] === "{" || state.src[start - 1] === "$")
return false;
const search = searchProps(state.src, start);
if (!search)
return false;
const {
props,
index: end
} = search;
if (end === start)
return false;
state.pos = end;
if (silent)
return true;
const token = state.push("mdc_inline_props", "span", 0);
token.attrs = props;
token.hidden = true;
return true;
});
md.renderer.rules.mdc_inline_props = () => {
return "";
};
const _parse = md.parse;
md.parse = function(src, env) {
const tokens = _parse.call(this, src, env);
tokens.forEach((token, index) => {
const prev = tokens[index - 1];
const next = tokens[index + 1];
if (!["heading_open", "paragraph_open", "list_item_open"].includes(prev?.type) || prev.hidden)
return;
if (token.hidden && next.type === "inline")
token = next;
if (token.type === "inline" && token.children?.length === 2 && token.children[0].type === "text" && token.children[1].type === "mdc_inline_props") {
const props = token.children[1].attrs;
token.children.splice(1, 1);
props?.forEach(([key, value]) => {
if (key === "class")
prev.attrJoin("class", value);
else
prev.attrSet(key, value);
});
}
});
tokens.forEach((tokenOpen, index) => {
if (tokenOpen.type !== "bullet_list_open")
return;
const prev = tokens[index - 1];
if (!prev || prev.type !== "mdc_block_open" || prev.tag !== "ul")
return;
let closeIndex = index + 1;
while (closeIndex < tokens.length) {
const close = tokens[closeIndex];
if (close.type === "bullet_list_close" && close.level === tokenOpen.level)
break;
closeIndex += 1;
}
const tokenClose = tokens[closeIndex];
if (tokenClose.type !== "bullet_list_close")
return;
const next = tokens[closeIndex + 1];
if (next.type === "mdc_block_close" && next.tag === "ul") {
tokenOpen.hidden = true;
tokenClose.hidden = true;
}
});
return tokens;
};
const _renderInline = md.renderer.renderInline;
md.renderer.renderInline = function(tokens, options, env) {
tokens = [...tokens];
tokens.forEach((token, index) => {
if (token.type === "mdc_inline_props") {
let prevIndex = index - 1;
let prev = tokens[prevIndex];
while (prevIndex >= 0) {
if (prev.type === "text" && !prev.content.trim()) {
prevIndex--;
prev = tokens[prevIndex];
} else {
break;
}
}
if (!prev.tag && prev.type === "text") {
prev = new TokenClass("mdc_inline_span", "span", 1);
tokens.splice(index - 1, 0, prev);
const close = new TokenClass("mdc_inline_span", "span", -1);
tokens.splice(index + 2, 0, close);
} else if (prev.nesting === -1) {
let searchIndex = index - 1;
while (searchIndex >= 0) {
const searchToken = tokens[searchIndex];
if (searchToken.nesting === 1 && searchToken.tag === prev.tag && searchToken.level === prev.level) {
prev = searchToken;
break;
}
searchIndex--;
}
}
if (prev.nesting === -1)
throw new Error(`No matching opening tag found for ${JSON.stringify(prev)}`);
token.attrs?.forEach(([key, value]) => {
if (key === "class")
prev.attrJoin("class", value);
else
prev.attrSet(key, value);
});
}
});
return _renderInline.call(this, tokens, options, env);
};
};
const MarkdownItInlineSpan = (md) => {
md.inline.ruler.before("link", "mdc_inline_span", (state, silent) => {
const start = state.pos;
const char = state.src[start];
if (char !== "[")
return false;
let index = start + 1;
let depth = 0;
while (index < state.src.length) {
if (state.src[index] === "\\") {
index += 2;
continue;
}
if (state.src[index] === "[") {
depth++;
} else if (state.src[index] === "]") {
if (depth === 0)
break;
depth--;
}
index += 1;
}
if (index === start)
return false;
const nextChar = state.src[index + 1];
if (nextChar === "(" || nextChar === "[")
return false;
if (silent)
return true;
state.push("mdc_inline_span", "span", 1);
const oldPos = state.pos;
const oldPosMax = state.posMax;
state.pos = start + 1;
state.posMax = index;
state.md.inline.tokenize(state);
state.pos = oldPos;
state.posMax = oldPosMax;
state.push("mdc_inline_span", "span", -1);
state.pos = index + 1;
return true;
});
};
const MarkdownItMdc = (md, options = {}) => {
const {
blockComponent = true,
inlineProps = true,
inlineSpan = true,
inlineComponent = true
} = options.syntax || {};
if (blockComponent)
md.use(MarkdownItMdcBlock);
if (inlineProps)
md.use(MarkdownItInlineProps);
if (inlineSpan)
md.use(MarkdownItInlineSpan);
if (inlineComponent)
md.use(MarkdownItInlineComponent);
};
export { MarkdownItMdc as default };
+86
View File
@@ -0,0 +1,86 @@
{
"name": "markdown-it-mdc",
"type": "module",
"version": "0.2.12",
"description": "Markdown Components (MDC) support for markdown-it",
"author": "Anthony Fu <anthonyfu117@hotmail.com>",
"license": "MIT",
"funding": "https://github.com/sponsors/antfu",
"homepage": "https://github.com/nuxt-content/markdown-it-mdc#readme",
"repository": {
"type": "git",
"url": "git+https://github.com/nuxt-content/markdown-it-mdc.git"
},
"bugs": "https://github.com/nuxt-content/markdown-it-mdc/issues",
"keywords": [
"markdown",
"markdown-it-plugin"
],
"sideEffects": false,
"exports": {
".": {
"types": "./dist/index.d.ts",
"import": "./dist/index.mjs"
}
},
"main": "./dist/index.mjs",
"module": "./dist/index.mjs",
"types": "./dist/index.d.ts",
"typesVersions": {
"*": {
"*": [
"./dist/*",
"./dist/index.d.ts"
]
}
},
"files": [
"dist"
],
"peerDependencies": {
"@types/markdown-it": "*",
"markdown-it": "^14.0.0"
},
"dependencies": {
"yaml": "^2.8.2"
},
"devDependencies": {
"@antfu/eslint-config": "^7.4.2",
"@antfu/ni": "^28.2.0",
"@antfu/utils": "^9.3.0",
"@mdit-vue/plugin-component": "^3.0.2",
"@mdit-vue/plugin-frontmatter": "^3.0.2",
"@types/markdown-it-container": "^4.0.0",
"@types/node": "^25.2.2",
"bumpp": "^10.4.1",
"eslint": "^10.0.0",
"lint-staged": "^16.2.7",
"markdown-it": "^14.1.0",
"markdown-it-container": "^4.0.0",
"markdown-it-task-checkbox": "^1.0.6",
"pnpm": "^10.29.2",
"prettier": "^3.8.1",
"scule": "^1.3.0",
"simple-git-hooks": "^2.13.1",
"tsx": "^4.21.0",
"typescript": "^5.9.3",
"unbuild": "^3.6.1",
"vite": "^7.3.1",
"vitest": "^4.0.18"
},
"simple-git-hooks": {
"pre-commit": "pnpm lint-staged"
},
"lint-staged": {
"*": "eslint --fix"
},
"scripts": {
"build": "unbuild",
"dev": "unbuild --stub",
"lint": "eslint .",
"release": "bumpp",
"start": "tsx src/index.ts",
"test": "vitest",
"typecheck": "tsc --noEmit"
}
}