@dogsbay/markdown-it-mdx-jsx 0.2.0-beta.12 → 0.2.0-beta.121
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/index.d.ts +7 -0
- package/dist/index.js +68 -10
- package/package.json +5 -5
package/dist/index.d.ts
CHANGED
|
@@ -16,6 +16,13 @@ export interface MdxJsxOptions {
|
|
|
16
16
|
components?: string[];
|
|
17
17
|
/** Tags that are always self-closing even without `/>`. */
|
|
18
18
|
selfClosing?: string[];
|
|
19
|
+
/**
|
|
20
|
+
* A self-closing tag followed by TEXT on its line opens a paragraph (the
|
|
21
|
+
* tag inline), as MDX reads it, instead of a block that dropped the rest of
|
|
22
|
+
* the line. Opt-in: a host must then handle (or report) inline components,
|
|
23
|
+
* or the component is lost instead of the text.
|
|
24
|
+
*/
|
|
25
|
+
inlineWhenFollowedByText?: boolean;
|
|
19
26
|
}
|
|
20
27
|
/**
|
|
21
28
|
* Parse JSX-style attributes from a string.
|
package/dist/index.js
CHANGED
|
@@ -271,7 +271,10 @@ function parseBlockTag(state, startLine, endLine, offset = 0) {
|
|
|
271
271
|
let combined = remaining;
|
|
272
272
|
let currentLine = startLine + 1;
|
|
273
273
|
while (currentLine < endLine) {
|
|
274
|
-
|
|
274
|
+
// The whole line, indentation included: a multi-line attribute VALUE
|
|
275
|
+
// (`<Code code={`…`} />`) is content, and trimming each line flattened
|
|
276
|
+
// every code sample written that way.
|
|
277
|
+
const nextLine = state.src.slice(state.bMarks[currentLine], state.eMarks[currentLine]);
|
|
275
278
|
combined += "\n" + nextLine;
|
|
276
279
|
const parsed = parseTag(combined, 0);
|
|
277
280
|
if (parsed) {
|
|
@@ -300,10 +303,21 @@ function createJsxBlockRule(options) {
|
|
|
300
303
|
return false;
|
|
301
304
|
if (componentSet && !componentSet.has(parsed.tag))
|
|
302
305
|
return false;
|
|
303
|
-
if (silent)
|
|
304
|
-
return true;
|
|
305
306
|
const lineEnd = state.eMarks[startLine];
|
|
306
307
|
const lineText = state.src.slice(pos, lineEnd);
|
|
308
|
+
// A self-closing tag followed by TEXT on its line opens a paragraph, as in
|
|
309
|
+
// MDX (`<Badge text="Beta" /> Connected meetings let you…`): taken as a
|
|
310
|
+
// block, the rest of the line was dropped. Another tag after it is still
|
|
311
|
+
// flow (`<Tabs> <TabItem>`), handled below.
|
|
312
|
+
if (options.inlineWhenFollowedByText && parsed.endLine === startLine && parsed.selfClosing) {
|
|
313
|
+
const rest = lineText.slice(parsed.length).trim();
|
|
314
|
+
// Another tag or a trailing `{…}` expression (`{/* c */}`, `{" "}`) is
|
|
315
|
+
// still flow; only prose makes it a paragraph.
|
|
316
|
+
if (rest && !rest.startsWith("<") && !rest.startsWith("{"))
|
|
317
|
+
return false;
|
|
318
|
+
}
|
|
319
|
+
if (silent)
|
|
320
|
+
return true;
|
|
307
321
|
// Process this tag and any subsequent tags on the same line
|
|
308
322
|
return processFlowTags(state, startLine, endLine, pos, lineText, componentSet, selfClosingSet);
|
|
309
323
|
};
|
|
@@ -406,6 +420,7 @@ function processFlowTags(state, startLine, endLine, linePos, lineText, component
|
|
|
406
420
|
return true;
|
|
407
421
|
}
|
|
408
422
|
// ── Inline rule ────────────────────────────────────────────
|
|
423
|
+
const openInline = new WeakMap();
|
|
409
424
|
function createJsxInlineRule(options) {
|
|
410
425
|
const componentSet = options.components ? new Set(options.components) : null;
|
|
411
426
|
const selfClosingSet = new Set(options.selfClosing || []);
|
|
@@ -418,11 +433,23 @@ function createJsxInlineRule(options) {
|
|
|
418
433
|
return false;
|
|
419
434
|
if (componentSet && !componentSet.has(parsed.tag))
|
|
420
435
|
return false;
|
|
421
|
-
|
|
436
|
+
// In silent mode (link-label scanning) the rule must still CONSUME the
|
|
437
|
+
// tag: returning true without moving pos threw "inline rule didn't
|
|
438
|
+
// increment state.pos" for any JSX inside `[label](url)`.
|
|
439
|
+
if (silent) {
|
|
440
|
+
state.pos += parsed.length;
|
|
422
441
|
return true;
|
|
442
|
+
}
|
|
423
443
|
const isSelfClosing = parsed.selfClosing || selfClosingSet.has(parsed.tag);
|
|
444
|
+
// Open inline tags in THIS inline run. A closer with no opener here (its
|
|
445
|
+
// opener sat in another paragraph) must not be nesting -1: markdown-it
|
|
446
|
+
// pops its delimiter stack on every -1, and an unmatched pop left it
|
|
447
|
+
// undefined, crashing the parse in balance_pairs.
|
|
448
|
+
const open = openInline.get(state) ?? 0;
|
|
424
449
|
if (parsed.isClose) {
|
|
425
|
-
const token = state.push("jsx_inline_close", parsed.tag, -1);
|
|
450
|
+
const token = state.push("jsx_inline_close", parsed.tag, open > 0 ? -1 : 0);
|
|
451
|
+
if (open > 0)
|
|
452
|
+
openInline.set(state, open - 1);
|
|
426
453
|
token.markup = `</${parsed.tag}>`;
|
|
427
454
|
}
|
|
428
455
|
else if (isSelfClosing) {
|
|
@@ -431,6 +458,7 @@ function createJsxInlineRule(options) {
|
|
|
431
458
|
}
|
|
432
459
|
else {
|
|
433
460
|
const token = state.push("jsx_inline_open", parsed.tag, 1);
|
|
461
|
+
openInline.set(state, open + 1);
|
|
434
462
|
token.meta = { attrs: parsed.attrs };
|
|
435
463
|
token.markup = `<${parsed.tag}>`;
|
|
436
464
|
}
|
|
@@ -480,6 +508,13 @@ function createImportStripRule() {
|
|
|
480
508
|
state.line = startLine + 1;
|
|
481
509
|
return true;
|
|
482
510
|
}
|
|
511
|
+
// Side-effect import (no binding): `import "./styles.module.css";`
|
|
512
|
+
if (text.match(/^import\s+["'][^"']*["']\s*;?\s*$/)) {
|
|
513
|
+
if (silent)
|
|
514
|
+
return true;
|
|
515
|
+
state.line = startLine + 1;
|
|
516
|
+
return true;
|
|
517
|
+
}
|
|
483
518
|
if (text.match(/^import\s*\{/)) {
|
|
484
519
|
if (silent)
|
|
485
520
|
return true;
|
|
@@ -514,11 +549,34 @@ function createImportStripRule() {
|
|
|
514
549
|
* Exported so consumers can call it before md.parse() if needed.
|
|
515
550
|
*/
|
|
516
551
|
export function normalizeJsxLines(source) {
|
|
517
|
-
//
|
|
518
|
-
|
|
519
|
-
//
|
|
520
|
-
|
|
521
|
-
return
|
|
552
|
+
// Line by line, and never inside a fence or a table row: a row is ONE
|
|
553
|
+
// line by definition, and splitting `</p> <Example>` out of a cell broke
|
|
554
|
+
// the table in two; a fence shows its JSX as code.
|
|
555
|
+
let fence = null;
|
|
556
|
+
return source
|
|
557
|
+
.split("\n")
|
|
558
|
+
.map((line) => {
|
|
559
|
+
const m = /^[ \t]*(`{3,}|~{3,})/.exec(line);
|
|
560
|
+
if (fence) {
|
|
561
|
+
if (m && m[1][0] === fence[0] && m[1].length >= fence.length && line.trim() === m[1])
|
|
562
|
+
fence = null;
|
|
563
|
+
return line;
|
|
564
|
+
}
|
|
565
|
+
// A backtick fence's info string cannot hold a backtick: "```x@y```"
|
|
566
|
+
// is an inline code span, and taking it for a fence switched this off
|
|
567
|
+
// for the rest of the document.
|
|
568
|
+
if (m && !(m[1][0] === "`" && line.slice(line.indexOf(m[1]) + m[1].length).includes("`"))) {
|
|
569
|
+
fence = m[1];
|
|
570
|
+
return line;
|
|
571
|
+
}
|
|
572
|
+
if (/^[ \t]*\|/.test(line))
|
|
573
|
+
return line;
|
|
574
|
+
// Split close tag + open/close tag: </X> <Y or </X> </Y
|
|
575
|
+
const once = line.replace(/(<\/[A-Z]\w*\s*>)([ \t]+)(<\/?[A-Z])/g, "$1\n$3");
|
|
576
|
+
// Split open tag end + next tag: ...> <Y (for <Tabs> <TabItem> pattern)
|
|
577
|
+
return once.replace(/(>)([ \t]+)(<\/?[A-Z]\w*[\s>])/g, "$1\n$3");
|
|
578
|
+
})
|
|
579
|
+
.join("\n");
|
|
522
580
|
}
|
|
523
581
|
// ── Plugin entry point ─────────────────────────────────────
|
|
524
582
|
export default function mdxJsxPlugin(md, options = {}) {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@dogsbay/markdown-it-mdx-jsx",
|
|
3
|
-
"version": "0.2.0-beta.
|
|
3
|
+
"version": "0.2.0-beta.121",
|
|
4
4
|
"description": "markdown-it plugin that tokenizes JSX-style component tags inside Markdown — used by @dogsbay/format-starlight",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"exports": {
|
|
@@ -11,13 +11,13 @@
|
|
|
11
11
|
"README.md"
|
|
12
12
|
],
|
|
13
13
|
"dependencies": {
|
|
14
|
-
"markdown-it": "^14.
|
|
14
|
+
"markdown-it": "^14.3.0"
|
|
15
15
|
},
|
|
16
16
|
"devDependencies": {
|
|
17
|
-
"@types/node": "^22.0.0",
|
|
18
17
|
"@types/markdown-it": "^14.1.2",
|
|
19
|
-
"
|
|
20
|
-
"
|
|
18
|
+
"@types/node": "^22.20.1",
|
|
19
|
+
"typescript": "^5.9.3",
|
|
20
|
+
"vitest": "^4.1.10"
|
|
21
21
|
},
|
|
22
22
|
"license": "MIT",
|
|
23
23
|
"repository": {
|