@godxjp/markdown 31.27.0 → 31.28.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/codec/index.d.ts +16 -2
- package/dist/codec/index.js +37 -2
- package/dist/index.d.ts +14 -1
- package/dist/index.js +32 -5
- package/package.json +3 -1
package/dist/codec/index.d.ts
CHANGED
|
@@ -10,7 +10,7 @@
|
|
|
10
10
|
* and the kit's own:
|
|
11
11
|
* callout{kind,title} · details · detailsSummary · detailsContent · columns · column{width} ·
|
|
12
12
|
* embed{target} (block `![[x]]`) · wikilink{target,heading,label} · embedInline{target} ·
|
|
13
|
-
* rawBlock{source} · rawInline{source}
|
|
13
|
+
* rawBlock{source} · rawInline{source} · frontmatter{source} (YAML, first block only)
|
|
14
14
|
* Marks: bold · italic · strike · code · link{href,title}.
|
|
15
15
|
*/
|
|
16
16
|
type Mark = {
|
|
@@ -43,6 +43,20 @@ declare const COLUMNS_MAX = 4;
|
|
|
43
43
|
/** Markdown → document (plain JSON, ProseMirror/Tiptap shape). Pure: no DOM. */
|
|
44
44
|
declare function parse(markdown: string): Doc;
|
|
45
45
|
|
|
46
|
+
type OutlineEntry = {
|
|
47
|
+
depth: number;
|
|
48
|
+
text: string;
|
|
49
|
+
id: string;
|
|
50
|
+
};
|
|
51
|
+
/**
|
|
52
|
+
* The body's headings with the ids `<Markdown>` gives them — GitHub slugs, de-duplicated in
|
|
53
|
+
* document order, the renderer's default rule — for a table of contents (the kit's `Anchor`). Pure.
|
|
54
|
+
* A host that passes its own `headingId` resolver to `<Markdown>` must use that same resolver here.
|
|
55
|
+
*/
|
|
56
|
+
declare function outline(markdown: string): OutlineEntry[];
|
|
57
|
+
/** The body's YAML front matter, verbatim (without the `---` fences), or null. Parse it with your YAML library. */
|
|
58
|
+
declare function frontmatterOf(markdown: string): string | null;
|
|
59
|
+
|
|
46
60
|
/** Document → canonical Markdown. Pure: no DOM. */
|
|
47
61
|
declare function serialize(doc: Doc | DocNode): string;
|
|
48
62
|
|
|
@@ -54,4 +68,4 @@ declare const CODEC_ID = "kit-md@1";
|
|
|
54
68
|
/** `serialize(parse(markdown))` — the canonical form of a body, exactly what the editor saves. */
|
|
55
69
|
declare function normalize(markdown: string): string;
|
|
56
70
|
|
|
57
|
-
export { CALLOUT_KINDS, CODEC_ID, COLUMNS_MAX, COLUMNS_MIN, type CalloutKind, type Doc, type DocNode, type Mark, normalize, parse, serialize };
|
|
71
|
+
export { CALLOUT_KINDS, CODEC_ID, COLUMNS_MAX, COLUMNS_MIN, type CalloutKind, type Doc, type DocNode, type Mark, type OutlineEntry, frontmatterOf, normalize, outline, parse, serialize };
|
package/dist/codec/index.js
CHANGED
|
@@ -73,15 +73,17 @@ function readColumns(node, nested) {
|
|
|
73
73
|
import { directive } from "micromark-extension-directive";
|
|
74
74
|
import { gfm } from "micromark-extension-gfm";
|
|
75
75
|
import { cjkFriendlyExtension } from "micromark-extension-cjk-friendly";
|
|
76
|
+
import { frontmatter } from "micromark-extension-frontmatter";
|
|
77
|
+
import { frontmatterFromMarkdown, frontmatterToMarkdown } from "mdast-util-frontmatter";
|
|
76
78
|
import { directiveFromMarkdown } from "mdast-util-directive";
|
|
77
79
|
import { gfmFromMarkdown, gfmToMarkdown } from "mdast-util-gfm";
|
|
78
80
|
function micromarkExtensions() {
|
|
79
81
|
const [container] = directive().flow[58];
|
|
80
82
|
const containerOnly = { flow: { 58: container } };
|
|
81
|
-
return [gfm(), cjkFriendlyExtension(), containerOnly];
|
|
83
|
+
return [gfm(), cjkFriendlyExtension(), frontmatter(["yaml"]), containerOnly];
|
|
82
84
|
}
|
|
83
85
|
function fromMarkdownExtensions() {
|
|
84
|
-
return [gfmFromMarkdown(), directiveFromMarkdown()];
|
|
86
|
+
return [gfmFromMarkdown(), directiveFromMarkdown(), frontmatterFromMarkdown(["yaml"])];
|
|
85
87
|
}
|
|
86
88
|
var WIDE = /[\u1100-\u115F\u2E80-\u303E\u3041-\u33FF\u3400-\u4DBF\u4E00-\u9FFF\uA000-\uA4CF\uAC00-\uD7A3\uF900-\uFAFF\uFE30-\uFE4F\uFF00-\uFF60\uFFE0-\uFFE6\u{1F300}-\u{1F64F}\u{1F900}-\u{1F9FF}\u{20000}-\u{3FFFD}]/u;
|
|
87
89
|
function displayWidth(value) {
|
|
@@ -92,6 +94,9 @@ function displayWidth(value) {
|
|
|
92
94
|
function toMarkdownGfm() {
|
|
93
95
|
return gfmToMarkdown({ stringLength: displayWidth });
|
|
94
96
|
}
|
|
97
|
+
function toMarkdownFrontmatter() {
|
|
98
|
+
return frontmatterToMarkdown(["yaml"]);
|
|
99
|
+
}
|
|
95
100
|
|
|
96
101
|
// src/codec/options.ts
|
|
97
102
|
function containerDirective(node, _, state, info) {
|
|
@@ -130,6 +135,7 @@ function toMarkdownOptions() {
|
|
|
130
135
|
resourceLink: false,
|
|
131
136
|
extensions: [
|
|
132
137
|
toMarkdownGfm(),
|
|
138
|
+
toMarkdownFrontmatter(),
|
|
133
139
|
{ handlers: { containerDirective } }
|
|
134
140
|
]
|
|
135
141
|
};
|
|
@@ -345,6 +351,8 @@ function block(node, depth) {
|
|
|
345
351
|
}
|
|
346
352
|
case "containerDirective":
|
|
347
353
|
return [directiveBlock(node, depth)];
|
|
354
|
+
case "yaml":
|
|
355
|
+
return [{ type: "frontmatter", attrs: { source: node.value } }];
|
|
348
356
|
default:
|
|
349
357
|
return [raw(node, false)];
|
|
350
358
|
}
|
|
@@ -536,6 +544,8 @@ function block2(node) {
|
|
|
536
544
|
return [{ type: "html", value: `![[${String(attrs.target)}]]` }];
|
|
537
545
|
case "rawBlock":
|
|
538
546
|
return [{ type: "html", value: String(attrs.source) }];
|
|
547
|
+
case "frontmatter":
|
|
548
|
+
return [{ type: "yaml", value: String(attrs.source) }];
|
|
539
549
|
default:
|
|
540
550
|
return [];
|
|
541
551
|
}
|
|
@@ -560,6 +570,29 @@ function serialize(doc) {
|
|
|
560
570
|
return decodeAttentionReferences(tidy);
|
|
561
571
|
}
|
|
562
572
|
|
|
573
|
+
// src/codec/outline.ts
|
|
574
|
+
import GithubSlugger from "github-slugger";
|
|
575
|
+
import { visit } from "unist-util-visit";
|
|
576
|
+
function textOf(node) {
|
|
577
|
+
if (node.type === "text" || node.type === "inlineCode" || node.type === "html") return node.value;
|
|
578
|
+
if (node.type === "image" || node.type === "imageReference") return "";
|
|
579
|
+
if ("children" in node) return node.children.map(textOf).join("");
|
|
580
|
+
return "";
|
|
581
|
+
}
|
|
582
|
+
function outline(markdown) {
|
|
583
|
+
const slugger = new GithubSlugger();
|
|
584
|
+
const entries = [];
|
|
585
|
+
visit(parseMdast(markdown.replace(/\r\n?/g, "\n")), "heading", (node) => {
|
|
586
|
+
const text2 = textOf(node);
|
|
587
|
+
entries.push({ depth: node.depth, text: text2, id: slugger.slug(text2) });
|
|
588
|
+
});
|
|
589
|
+
return entries;
|
|
590
|
+
}
|
|
591
|
+
function frontmatterOf(markdown) {
|
|
592
|
+
const first = parseMdast(markdown.replace(/\r\n?/g, "\n")).children[0];
|
|
593
|
+
return first?.type === "yaml" ? first.value : null;
|
|
594
|
+
}
|
|
595
|
+
|
|
563
596
|
// src/codec/index.ts
|
|
564
597
|
var CODEC_ID = "kit-md@1";
|
|
565
598
|
function normalize(markdown) {
|
|
@@ -570,7 +603,9 @@ export {
|
|
|
570
603
|
CODEC_ID,
|
|
571
604
|
COLUMNS_MAX,
|
|
572
605
|
COLUMNS_MIN,
|
|
606
|
+
frontmatterOf,
|
|
573
607
|
normalize,
|
|
608
|
+
outline,
|
|
574
609
|
parse,
|
|
575
610
|
serialize
|
|
576
611
|
};
|
package/dist/index.d.ts
CHANGED
|
@@ -133,6 +133,19 @@ type MarkdownProps = {
|
|
|
133
133
|
* default — this package carries no i18n; a host passes its localized strings.
|
|
134
134
|
*/
|
|
135
135
|
calloutTitles?: Partial<Record<CalloutKind, string>>;
|
|
136
|
+
/**
|
|
137
|
+
* Where an EXTERNAL link opens. An external link is an absolute http(s) URL whose origin differs
|
|
138
|
+
* from `origin`. `"new-tab"` gives it `target="_blank"` and `rel="noopener noreferrer"`. Relative
|
|
139
|
+
* links, `#anchors`, wikilinks resolved to a path, and `mailto:` stay in the tab. The default,
|
|
140
|
+
* `"same-tab"`, changes nothing. Markdown has no syntax for `target`, so this is a renderer policy.
|
|
141
|
+
*/
|
|
142
|
+
externalLinks?: "same-tab" | "new-tab";
|
|
143
|
+
/**
|
|
144
|
+
* The page origin that `externalLinks` compares against. Defaults to `location.origin`. Pass it
|
|
145
|
+
* when rendering on the server, or every absolute link counts as external there and hydration
|
|
146
|
+
* disagrees on same-origin ones.
|
|
147
|
+
*/
|
|
148
|
+
origin?: string;
|
|
136
149
|
};
|
|
137
150
|
/**
|
|
138
151
|
* THE ONE RENDERER (gh#1108). GFM — tables, task lists, fenced code, autolinks, footnotes,
|
|
@@ -144,7 +157,7 @@ type MarkdownProps = {
|
|
|
144
157
|
* Renders bare elements; the host wraps it (`<Prose>` from `@godxjp/ui/data-display`), so this
|
|
145
158
|
* package carries no UI-kit dependency.
|
|
146
159
|
*/
|
|
147
|
-
declare function Markdown({ children, remarkPlugins, rehypePlugins, schema, components, resolveUrl, headingId, mermaid, allowedElements, disallowedElements, allowElement, unwrapDisallowed, shortCellLength, calloutTitles, }: MarkdownProps): React.JSX.Element;
|
|
160
|
+
declare function Markdown({ children, remarkPlugins, rehypePlugins, schema, components, resolveUrl, headingId, mermaid, allowedElements, disallowedElements, allowElement, unwrapDisallowed, shortCellLength, calloutTitles, externalLinks, origin, }: MarkdownProps): React.JSX.Element;
|
|
148
161
|
|
|
149
162
|
type MermaidSvgCheck = {
|
|
150
163
|
ok: true;
|
package/dist/index.js
CHANGED
|
@@ -339,15 +339,17 @@ function columnShares(columns) {
|
|
|
339
339
|
import { directive } from "micromark-extension-directive";
|
|
340
340
|
import { gfm } from "micromark-extension-gfm";
|
|
341
341
|
import { cjkFriendlyExtension } from "micromark-extension-cjk-friendly";
|
|
342
|
+
import { frontmatter } from "micromark-extension-frontmatter";
|
|
343
|
+
import { frontmatterFromMarkdown, frontmatterToMarkdown } from "mdast-util-frontmatter";
|
|
342
344
|
import { directiveFromMarkdown } from "mdast-util-directive";
|
|
343
345
|
import { gfmFromMarkdown, gfmToMarkdown } from "mdast-util-gfm";
|
|
344
346
|
function micromarkExtensions() {
|
|
345
347
|
const [container] = directive().flow[58];
|
|
346
348
|
const containerOnly = { flow: { 58: container } };
|
|
347
|
-
return [gfm(), cjkFriendlyExtension(), containerOnly];
|
|
349
|
+
return [gfm(), cjkFriendlyExtension(), frontmatter(["yaml"]), containerOnly];
|
|
348
350
|
}
|
|
349
351
|
function fromMarkdownExtensions() {
|
|
350
|
-
return [gfmFromMarkdown(), directiveFromMarkdown()];
|
|
352
|
+
return [gfmFromMarkdown(), directiveFromMarkdown(), frontmatterFromMarkdown(["yaml"])];
|
|
351
353
|
}
|
|
352
354
|
|
|
353
355
|
// src/directives.ts
|
|
@@ -367,7 +369,7 @@ function remarkKitSyntax(options = {}) {
|
|
|
367
369
|
return function() {
|
|
368
370
|
const data = this.data();
|
|
369
371
|
(data.micromarkExtensions ??= []).push(...micromarkExtensions().slice(1));
|
|
370
|
-
(data.fromMarkdownExtensions ??= []).push(fromMarkdownExtensions()
|
|
372
|
+
(data.fromMarkdownExtensions ??= []).push(...fromMarkdownExtensions().slice(1));
|
|
371
373
|
const walk = (node, inColumn) => {
|
|
372
374
|
if (node.type === "blockquote") callout(node, titles);
|
|
373
375
|
else if (node.type === "containerDirective") directive2(node, inColumn);
|
|
@@ -375,7 +377,10 @@ function remarkKitSyntax(options = {}) {
|
|
|
375
377
|
const isColumn = node.type === "containerDirective" && node.name === "column";
|
|
376
378
|
for (const child of node.children) walk(child, inColumn || isColumn);
|
|
377
379
|
};
|
|
378
|
-
return (tree) =>
|
|
380
|
+
return (tree) => {
|
|
381
|
+
tree.children = tree.children.filter((node) => node.type !== "yaml");
|
|
382
|
+
walk(tree, false);
|
|
383
|
+
};
|
|
379
384
|
};
|
|
380
385
|
}
|
|
381
386
|
function callout(node, titles) {
|
|
@@ -470,6 +475,25 @@ function rehypeShortCells(options) {
|
|
|
470
475
|
});
|
|
471
476
|
};
|
|
472
477
|
}
|
|
478
|
+
function rehypeExternalLinks(options) {
|
|
479
|
+
return (tree) => {
|
|
480
|
+
if (options.policy !== "new-tab") return;
|
|
481
|
+
const origin = options.origin ?? globalThis.location?.origin;
|
|
482
|
+
visit2(tree, "element", (node) => {
|
|
483
|
+
if (node.tagName !== "a") return;
|
|
484
|
+
const href = node.properties?.href;
|
|
485
|
+
if (typeof href !== "string" || !/^https?:\/\//i.test(href)) return;
|
|
486
|
+
let target;
|
|
487
|
+
try {
|
|
488
|
+
target = new URL(href);
|
|
489
|
+
} catch {
|
|
490
|
+
return;
|
|
491
|
+
}
|
|
492
|
+
if (origin && target.origin === origin) return;
|
|
493
|
+
node.properties = { ...node.properties, target: "_blank", rel: ["noopener", "noreferrer"] };
|
|
494
|
+
});
|
|
495
|
+
};
|
|
496
|
+
}
|
|
473
497
|
function omitNode(props) {
|
|
474
498
|
const { node: _node, ...rest } = props;
|
|
475
499
|
return rest;
|
|
@@ -496,7 +520,9 @@ function Markdown({
|
|
|
496
520
|
allowElement,
|
|
497
521
|
unwrapDisallowed,
|
|
498
522
|
shortCellLength = 24,
|
|
499
|
-
calloutTitles
|
|
523
|
+
calloutTitles,
|
|
524
|
+
externalLinks = "same-tab",
|
|
525
|
+
origin
|
|
500
526
|
}) {
|
|
501
527
|
const sanitizeSchema = React3.useMemo(() => extendSchema(schema), [schema]);
|
|
502
528
|
const kitSyntax = React3.useMemo(() => remarkKitSyntax({ calloutTitles }), [calloutTitles]);
|
|
@@ -524,6 +550,7 @@ function Markdown({
|
|
|
524
550
|
[rehypeHeadingIds, { resolve: headingId }],
|
|
525
551
|
[rehypeSanitize, sanitizeSchema],
|
|
526
552
|
[rehypeShortCells, { max: shortCellLength }],
|
|
553
|
+
[rehypeExternalLinks, { policy: externalLinks, origin }],
|
|
527
554
|
...rehypePlugins
|
|
528
555
|
],
|
|
529
556
|
urlTransform: safeUrl,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@godxjp/markdown",
|
|
3
|
-
"version": "31.
|
|
3
|
+
"version": "31.28.0",
|
|
4
4
|
"description": "The one Markdown renderer for GoDX apps: GFM + heading anchors, one sanitiser schema, a shared fixture corpus, and Mermaid drawn only after its SVG passes a fail-closed gate.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.js",
|
|
@@ -36,10 +36,12 @@
|
|
|
36
36
|
"github-slugger": "^2.0.0",
|
|
37
37
|
"mdast-util-directive": "^3.1.1",
|
|
38
38
|
"mdast-util-from-markdown": "^2.1.0",
|
|
39
|
+
"mdast-util-frontmatter": "^2.0.1",
|
|
39
40
|
"mdast-util-gfm": "^3.1.0",
|
|
40
41
|
"mdast-util-to-markdown": "^2.2.0",
|
|
41
42
|
"micromark-extension-cjk-friendly": "^2.0.2",
|
|
42
43
|
"micromark-extension-directive": "^4.0.0",
|
|
44
|
+
"micromark-extension-frontmatter": "^2.0.0",
|
|
43
45
|
"micromark-extension-gfm": "^3.0.0",
|
|
44
46
|
"micromark-util-types": "^2.0.2",
|
|
45
47
|
"react-markdown": "^10.1.0",
|