@mdfn/extensions 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.
package/README.md ADDED
@@ -0,0 +1,5 @@
1
+ # @mdfn/extensions
2
+
3
+ Certified extension declarations and helpers. Each extension declares syntax
4
+ ownership, conflicts, dependencies, preservation, security, diagnostics, and
5
+ migrations.
@@ -0,0 +1,153 @@
1
+ "use strict";
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __export = (target, all) => {
7
+ for (var name in all)
8
+ __defProp(target, name, { get: all[name], enumerable: true });
9
+ };
10
+ var __copyProps = (to, from, except, desc) => {
11
+ if (from && typeof from === "object" || typeof from === "function") {
12
+ for (let key of __getOwnPropNames(from))
13
+ if (!__hasOwnProp.call(to, key) && key !== except)
14
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
+ }
16
+ return to;
17
+ };
18
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
+
20
+ // src/callout.ts
21
+ var callout_exports = {};
22
+ __export(callout_exports, {
23
+ calloutExtension: () => calloutExtension
24
+ });
25
+ module.exports = __toCommonJS(callout_exports);
26
+
27
+ // src/index.ts
28
+ var exactPreservation = {
29
+ noEdit: "exact",
30
+ edited: "touched-region",
31
+ unsupported: "opaque"
32
+ };
33
+ var commonmarkExtension = {
34
+ name: "commonmark",
35
+ version: "1.0.0",
36
+ schema: {
37
+ nodes: ["doc", "paragraph", "heading", "blockquote", "list", "listItem", "codeBlock", "inlineCode", "thematicBreak", "hardBreak", "text", "strong", "emphasis", "link", "image", "opaque"],
38
+ marks: ["strong", "emphasis", "code", "link"]
39
+ },
40
+ preservation: exactPreservation,
41
+ security: { allowsRawHtml: false, urlSchemes: ["http", "https", "mailto"] }
42
+ };
43
+ var gfmExtension = {
44
+ name: "gfm",
45
+ version: "1.0.0",
46
+ dependencies: ["commonmark"],
47
+ schema: { nodes: ["table", "tableRow", "tableCell", "taskListItem", "delete"], marks: ["delete"] },
48
+ preservation: exactPreservation,
49
+ security: { allowsRawHtml: false, urlSchemes: ["http", "https", "mailto"] }
50
+ };
51
+ function directiveName(value) {
52
+ if (!/^[a-z][a-z0-9-]*$/.test(value)) throw new TypeError(`MDFN_DIRECTIVE_NAME_INVALID:${value}`);
53
+ return value;
54
+ }
55
+ function createDirectiveExtension(options) {
56
+ const name = directiveName(options.name);
57
+ const nodeType = `directive-${name}`;
58
+ return {
59
+ name: `directive/${name}`,
60
+ version: options.version ?? "1.0.0",
61
+ dependencies: ["commonmark"],
62
+ schema: { nodes: [nodeType] },
63
+ preservation: exactPreservation,
64
+ security: { allowsRawHtml: false },
65
+ parseMarkdown({ source, offset, line }) {
66
+ const opening = new RegExp(`^(:{3,})[ \\t]*${name}(?:[ \\t]+([^\\r\\n]*?))?[ \\t]*(?:\\r?\\n|\\r|$)`).exec(line);
67
+ if (!opening) return null;
68
+ const searchFrom = offset + line.length;
69
+ const closePattern = new RegExp(`^:{${opening[1].length},}[ \\t]*(?:\\r?\\n|\\r|$)`, "gm");
70
+ closePattern.lastIndex = searchFrom;
71
+ const close = closePattern.exec(source);
72
+ const closeEnd = close ? close.index + close[0].length : source.length;
73
+ const bodyEnd = close?.index ?? source.length;
74
+ const body = source.slice(searchFrom, bodyEnd).replace(/\r?\n$/, "");
75
+ return {
76
+ consumed: closeEnd - offset,
77
+ node: {
78
+ type: nodeType,
79
+ attrs: { name, label: opening[2]?.trim() || options.label || name },
80
+ text: body
81
+ },
82
+ diagnostics: close ? [] : [{ code: "MDFN_DIRECTIVE_UNCLOSED", message: `Directive ${name} has no closing fence`, severity: "warning", source: { from: offset, to: source.length }, extension: `directive/${name}` }]
83
+ };
84
+ },
85
+ serializeMarkdown({ node }) {
86
+ if (node.type !== nodeType) return null;
87
+ const label = typeof node.attrs?.label === "string" && node.attrs.label !== name ? ` ${node.attrs.label}` : "";
88
+ const body = node.text ?? "";
89
+ let fenceLength = 3;
90
+ for (const match of body.matchAll(/^(:{3,})[ \\t]*(?:\\r)?$/gm)) fenceLength = Math.max(fenceLength, match[1].length + 1);
91
+ const fence = ":".repeat(fenceLength);
92
+ return `${fence}${name}${label}
93
+ ${body}
94
+ ${fence}`;
95
+ },
96
+ render({ node }) {
97
+ if (node.type !== nodeType) return null;
98
+ const label = typeof node.attrs?.label === "string" ? node.attrs.label : options.label ?? name;
99
+ const classes = ["mdfn-directive", `mdfn-directive-${name}`, options.className].filter(Boolean).join(" ");
100
+ return {
101
+ tag: "aside",
102
+ attrs: { class: classes, "data-md-directive": name },
103
+ children: [
104
+ { tag: "strong", text: label },
105
+ { tag: "p", text: node.text ?? "" }
106
+ ]
107
+ };
108
+ },
109
+ visual({ node }) {
110
+ if (node.type !== nodeType) return null;
111
+ const label = typeof node.attrs?.label === "string" ? node.attrs.label : options.label ?? name;
112
+ return {
113
+ tag: "aside",
114
+ attrs: { class: "mdfn-directive-visual", "data-md-directive": name },
115
+ children: [
116
+ { tag: "strong", text: label },
117
+ { tag: "p", text: node.text ?? "" }
118
+ ]
119
+ };
120
+ },
121
+ diagnostics(document) {
122
+ const diagnostics = [];
123
+ const visit = (node) => {
124
+ if (node.type === nodeType && !(node.text ?? "").trim()) diagnostics.push({ code: "MDFN_DIRECTIVE_EMPTY", message: `Directive ${name} is empty`, severity: "warning", nodeId: node.id, extension: `directive/${name}` });
125
+ node.content?.forEach(visit);
126
+ };
127
+ visit(document);
128
+ return diagnostics;
129
+ },
130
+ migrations: [{
131
+ from: 1,
132
+ to: 2,
133
+ migrate(document) {
134
+ const migrate = (node) => node.type === `callout-${name}` ? { ...node, type: nodeType } : { ...node, content: node.content?.map(migrate) };
135
+ return { ...migrate(document), type: "doc", schemaVersion: 2 };
136
+ }
137
+ }],
138
+ certification: {
139
+ schemaVersion: 1,
140
+ fixtures: [`directive-${name}`],
141
+ capabilities: ["parse", "serialize", "render", "visual", "diagnostics", "migrations", "security"]
142
+ }
143
+ };
144
+ }
145
+ var calloutExtension = createDirectiveExtension({ name: "callout", label: "Callout" });
146
+ var diagramExtension = createDirectiveExtension({ name: "diagram", label: "Diagram" });
147
+ var defaultExtensions = Object.freeze([commonmarkExtension, gfmExtension]);
148
+ var authoringExtensions = Object.freeze([commonmarkExtension, gfmExtension, calloutExtension, diagramExtension]);
149
+ // Annotate the CommonJS export names for ESM import in node:
150
+ 0 && (module.exports = {
151
+ calloutExtension
152
+ });
153
+ //# sourceMappingURL=callout.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/callout.ts","../src/index.ts"],"sourcesContent":["export { calloutExtension } from \"./index\";\n","import type { MdfnDocument, MdfnExtension, MdfnNode } from \"@mdfn/core\";\n\nconst exactPreservation = {\n noEdit: \"exact\",\n edited: \"touched-region\",\n unsupported: \"opaque\",\n} as const;\n\nexport const commonmarkExtension: MdfnExtension = {\n name: \"commonmark\",\n version: \"1.0.0\",\n schema: {\n nodes: [\"doc\", \"paragraph\", \"heading\", \"blockquote\", \"list\", \"listItem\", \"codeBlock\", \"inlineCode\", \"thematicBreak\", \"hardBreak\", \"text\", \"strong\", \"emphasis\", \"link\", \"image\", \"opaque\"],\n marks: [\"strong\", \"emphasis\", \"code\", \"link\"],\n },\n preservation: exactPreservation,\n security: { allowsRawHtml: false, urlSchemes: [\"http\", \"https\", \"mailto\"] },\n};\n\nexport const gfmExtension: MdfnExtension = {\n name: \"gfm\",\n version: \"1.0.0\",\n dependencies: [\"commonmark\"],\n schema: { nodes: [\"table\", \"tableRow\", \"tableCell\", \"taskListItem\", \"delete\"], marks: [\"delete\"] },\n preservation: exactPreservation,\n security: { allowsRawHtml: false, urlSchemes: [\"http\", \"https\", \"mailto\"] },\n};\n\nexport interface DirectiveExtensionOptions {\n readonly name: string;\n readonly label?: string;\n readonly className?: string;\n readonly version?: string;\n}\n\nfunction directiveName(value: string): string {\n if (!/^[a-z][a-z0-9-]*$/.test(value)) throw new TypeError(`MDFN_DIRECTIVE_NAME_INVALID:${value}`);\n return value;\n}\n\nexport function createDirectiveExtension(options: DirectiveExtensionOptions): MdfnExtension {\n const name = directiveName(options.name);\n const nodeType = `directive-${name}`;\n return {\n name: `directive/${name}`,\n version: options.version ?? \"1.0.0\",\n dependencies: [\"commonmark\"],\n schema: { nodes: [nodeType] },\n preservation: exactPreservation,\n security: { allowsRawHtml: false },\n parseMarkdown({ source, offset, line }) {\n const opening = new RegExp(`^(:{3,})[ \\\\t]*${name}(?:[ \\\\t]+([^\\\\r\\\\n]*?))?[ \\\\t]*(?:\\\\r?\\\\n|\\\\r|$)`).exec(line);\n if (!opening) return null;\n const searchFrom = offset + line.length;\n const closePattern = new RegExp(`^:{${opening[1].length},}[ \\\\t]*(?:\\\\r?\\\\n|\\\\r|$)`, \"gm\");\n closePattern.lastIndex = searchFrom;\n const close = closePattern.exec(source);\n const closeEnd = close ? close.index + close[0].length : source.length;\n const bodyEnd = close?.index ?? source.length;\n const body = source.slice(searchFrom, bodyEnd).replace(/\\r?\\n$/, \"\");\n return {\n consumed: closeEnd - offset,\n node: {\n type: nodeType,\n attrs: { name, label: opening[2]?.trim() || options.label || name },\n text: body,\n },\n diagnostics: close ? [] : [{ code: \"MDFN_DIRECTIVE_UNCLOSED\", message: `Directive ${name} has no closing fence`, severity: \"warning\", source: { from: offset, to: source.length }, extension: `directive/${name}` }],\n };\n },\n serializeMarkdown({ node }) {\n if (node.type !== nodeType) return null;\n const label = typeof node.attrs?.label === \"string\" && node.attrs.label !== name ? ` ${node.attrs.label}` : \"\";\n const body = node.text ?? \"\";\n let fenceLength = 3;\n for (const match of body.matchAll(/^(:{3,})[ \\\\t]*(?:\\\\r)?$/gm)) fenceLength = Math.max(fenceLength, match[1].length + 1);\n const fence = \":\".repeat(fenceLength);\n return `${fence}${name}${label}\\n${body}\\n${fence}`;\n },\n render({ node }) {\n if (node.type !== nodeType) return null;\n const label = typeof node.attrs?.label === \"string\" ? node.attrs.label : options.label ?? name;\n const classes = [\"mdfn-directive\", `mdfn-directive-${name}`, options.className].filter(Boolean).join(\" \");\n return {\n tag: \"aside\",\n attrs: { class: classes, \"data-md-directive\": name },\n children: [\n { tag: \"strong\", text: label },\n { tag: \"p\", text: node.text ?? \"\" },\n ],\n };\n },\n visual({ node }) {\n if (node.type !== nodeType) return null;\n const label = typeof node.attrs?.label === \"string\" ? node.attrs.label : options.label ?? name;\n return {\n tag: \"aside\",\n attrs: { class: \"mdfn-directive-visual\", \"data-md-directive\": name },\n children: [\n { tag: \"strong\", text: label },\n { tag: \"p\", text: node.text ?? \"\" },\n ],\n };\n },\n diagnostics(document) {\n const diagnostics: Array<{ code: string; message: string; severity: \"warning\"; nodeId?: string; extension: string }> = [];\n const visit = (node: MdfnNode): void => {\n if (node.type === nodeType && !(node.text ?? \"\").trim()) diagnostics.push({ code: \"MDFN_DIRECTIVE_EMPTY\", message: `Directive ${name} is empty`, severity: \"warning\", nodeId: node.id, extension: `directive/${name}` });\n node.content?.forEach(visit);\n };\n visit(document);\n return diagnostics;\n },\n migrations: [{\n from: 1,\n to: 2,\n migrate(document: MdfnDocument): MdfnDocument {\n const migrate = (node: MdfnNode): MdfnNode => node.type === `callout-${name}`\n ? { ...node, type: nodeType }\n : { ...node, content: node.content?.map(migrate) };\n return { ...migrate(document), type: \"doc\", schemaVersion: 2 } as MdfnDocument;\n },\n }],\n certification: {\n schemaVersion: 1,\n fixtures: [`directive-${name}`],\n capabilities: [\"parse\", \"serialize\", \"render\", \"visual\", \"diagnostics\", \"migrations\", \"security\"],\n },\n };\n}\n\nexport const calloutExtension = createDirectiveExtension({ name: \"callout\", label: \"Callout\" });\nexport const diagramExtension = createDirectiveExtension({ name: \"diagram\", label: \"Diagram\" });\n\nexport const defaultExtensions = Object.freeze([commonmarkExtension, gfmExtension]);\nexport const authoringExtensions = Object.freeze([commonmarkExtension, gfmExtension, calloutExtension, diagramExtension]);\n\nexport const MDFN_EXTENSIONS_VERSION = \"0.1.0\" as const;\n"],"mappings":"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","names":[]}
@@ -0,0 +1,2 @@
1
+ export { calloutExtension } from './index.cjs';
2
+ import '@mdfn/core';
@@ -0,0 +1,2 @@
1
+ export { calloutExtension } from './index.js';
2
+ import '@mdfn/core';
@@ -0,0 +1,7 @@
1
+ import {
2
+ calloutExtension
3
+ } from "./chunk-4I3JGYQE.js";
4
+ export {
5
+ calloutExtension
6
+ };
7
+ //# sourceMappingURL=callout.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":[],"sourcesContent":[],"mappings":"","names":[]}
@@ -0,0 +1,135 @@
1
+ // src/index.ts
2
+ var exactPreservation = {
3
+ noEdit: "exact",
4
+ edited: "touched-region",
5
+ unsupported: "opaque"
6
+ };
7
+ var commonmarkExtension = {
8
+ name: "commonmark",
9
+ version: "1.0.0",
10
+ schema: {
11
+ nodes: ["doc", "paragraph", "heading", "blockquote", "list", "listItem", "codeBlock", "inlineCode", "thematicBreak", "hardBreak", "text", "strong", "emphasis", "link", "image", "opaque"],
12
+ marks: ["strong", "emphasis", "code", "link"]
13
+ },
14
+ preservation: exactPreservation,
15
+ security: { allowsRawHtml: false, urlSchemes: ["http", "https", "mailto"] }
16
+ };
17
+ var gfmExtension = {
18
+ name: "gfm",
19
+ version: "1.0.0",
20
+ dependencies: ["commonmark"],
21
+ schema: { nodes: ["table", "tableRow", "tableCell", "taskListItem", "delete"], marks: ["delete"] },
22
+ preservation: exactPreservation,
23
+ security: { allowsRawHtml: false, urlSchemes: ["http", "https", "mailto"] }
24
+ };
25
+ function directiveName(value) {
26
+ if (!/^[a-z][a-z0-9-]*$/.test(value)) throw new TypeError(`MDFN_DIRECTIVE_NAME_INVALID:${value}`);
27
+ return value;
28
+ }
29
+ function createDirectiveExtension(options) {
30
+ const name = directiveName(options.name);
31
+ const nodeType = `directive-${name}`;
32
+ return {
33
+ name: `directive/${name}`,
34
+ version: options.version ?? "1.0.0",
35
+ dependencies: ["commonmark"],
36
+ schema: { nodes: [nodeType] },
37
+ preservation: exactPreservation,
38
+ security: { allowsRawHtml: false },
39
+ parseMarkdown({ source, offset, line }) {
40
+ const opening = new RegExp(`^(:{3,})[ \\t]*${name}(?:[ \\t]+([^\\r\\n]*?))?[ \\t]*(?:\\r?\\n|\\r|$)`).exec(line);
41
+ if (!opening) return null;
42
+ const searchFrom = offset + line.length;
43
+ const closePattern = new RegExp(`^:{${opening[1].length},}[ \\t]*(?:\\r?\\n|\\r|$)`, "gm");
44
+ closePattern.lastIndex = searchFrom;
45
+ const close = closePattern.exec(source);
46
+ const closeEnd = close ? close.index + close[0].length : source.length;
47
+ const bodyEnd = close?.index ?? source.length;
48
+ const body = source.slice(searchFrom, bodyEnd).replace(/\r?\n$/, "");
49
+ return {
50
+ consumed: closeEnd - offset,
51
+ node: {
52
+ type: nodeType,
53
+ attrs: { name, label: opening[2]?.trim() || options.label || name },
54
+ text: body
55
+ },
56
+ diagnostics: close ? [] : [{ code: "MDFN_DIRECTIVE_UNCLOSED", message: `Directive ${name} has no closing fence`, severity: "warning", source: { from: offset, to: source.length }, extension: `directive/${name}` }]
57
+ };
58
+ },
59
+ serializeMarkdown({ node }) {
60
+ if (node.type !== nodeType) return null;
61
+ const label = typeof node.attrs?.label === "string" && node.attrs.label !== name ? ` ${node.attrs.label}` : "";
62
+ const body = node.text ?? "";
63
+ let fenceLength = 3;
64
+ for (const match of body.matchAll(/^(:{3,})[ \\t]*(?:\\r)?$/gm)) fenceLength = Math.max(fenceLength, match[1].length + 1);
65
+ const fence = ":".repeat(fenceLength);
66
+ return `${fence}${name}${label}
67
+ ${body}
68
+ ${fence}`;
69
+ },
70
+ render({ node }) {
71
+ if (node.type !== nodeType) return null;
72
+ const label = typeof node.attrs?.label === "string" ? node.attrs.label : options.label ?? name;
73
+ const classes = ["mdfn-directive", `mdfn-directive-${name}`, options.className].filter(Boolean).join(" ");
74
+ return {
75
+ tag: "aside",
76
+ attrs: { class: classes, "data-md-directive": name },
77
+ children: [
78
+ { tag: "strong", text: label },
79
+ { tag: "p", text: node.text ?? "" }
80
+ ]
81
+ };
82
+ },
83
+ visual({ node }) {
84
+ if (node.type !== nodeType) return null;
85
+ const label = typeof node.attrs?.label === "string" ? node.attrs.label : options.label ?? name;
86
+ return {
87
+ tag: "aside",
88
+ attrs: { class: "mdfn-directive-visual", "data-md-directive": name },
89
+ children: [
90
+ { tag: "strong", text: label },
91
+ { tag: "p", text: node.text ?? "" }
92
+ ]
93
+ };
94
+ },
95
+ diagnostics(document) {
96
+ const diagnostics = [];
97
+ const visit = (node) => {
98
+ if (node.type === nodeType && !(node.text ?? "").trim()) diagnostics.push({ code: "MDFN_DIRECTIVE_EMPTY", message: `Directive ${name} is empty`, severity: "warning", nodeId: node.id, extension: `directive/${name}` });
99
+ node.content?.forEach(visit);
100
+ };
101
+ visit(document);
102
+ return diagnostics;
103
+ },
104
+ migrations: [{
105
+ from: 1,
106
+ to: 2,
107
+ migrate(document) {
108
+ const migrate = (node) => node.type === `callout-${name}` ? { ...node, type: nodeType } : { ...node, content: node.content?.map(migrate) };
109
+ return { ...migrate(document), type: "doc", schemaVersion: 2 };
110
+ }
111
+ }],
112
+ certification: {
113
+ schemaVersion: 1,
114
+ fixtures: [`directive-${name}`],
115
+ capabilities: ["parse", "serialize", "render", "visual", "diagnostics", "migrations", "security"]
116
+ }
117
+ };
118
+ }
119
+ var calloutExtension = createDirectiveExtension({ name: "callout", label: "Callout" });
120
+ var diagramExtension = createDirectiveExtension({ name: "diagram", label: "Diagram" });
121
+ var defaultExtensions = Object.freeze([commonmarkExtension, gfmExtension]);
122
+ var authoringExtensions = Object.freeze([commonmarkExtension, gfmExtension, calloutExtension, diagramExtension]);
123
+ var MDFN_EXTENSIONS_VERSION = "0.1.0";
124
+
125
+ export {
126
+ commonmarkExtension,
127
+ gfmExtension,
128
+ createDirectiveExtension,
129
+ calloutExtension,
130
+ diagramExtension,
131
+ defaultExtensions,
132
+ authoringExtensions,
133
+ MDFN_EXTENSIONS_VERSION
134
+ };
135
+ //# sourceMappingURL=chunk-4I3JGYQE.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/index.ts"],"sourcesContent":["import type { MdfnDocument, MdfnExtension, MdfnNode } from \"@mdfn/core\";\n\nconst exactPreservation = {\n noEdit: \"exact\",\n edited: \"touched-region\",\n unsupported: \"opaque\",\n} as const;\n\nexport const commonmarkExtension: MdfnExtension = {\n name: \"commonmark\",\n version: \"1.0.0\",\n schema: {\n nodes: [\"doc\", \"paragraph\", \"heading\", \"blockquote\", \"list\", \"listItem\", \"codeBlock\", \"inlineCode\", \"thematicBreak\", \"hardBreak\", \"text\", \"strong\", \"emphasis\", \"link\", \"image\", \"opaque\"],\n marks: [\"strong\", \"emphasis\", \"code\", \"link\"],\n },\n preservation: exactPreservation,\n security: { allowsRawHtml: false, urlSchemes: [\"http\", \"https\", \"mailto\"] },\n};\n\nexport const gfmExtension: MdfnExtension = {\n name: \"gfm\",\n version: \"1.0.0\",\n dependencies: [\"commonmark\"],\n schema: { nodes: [\"table\", \"tableRow\", \"tableCell\", \"taskListItem\", \"delete\"], marks: [\"delete\"] },\n preservation: exactPreservation,\n security: { allowsRawHtml: false, urlSchemes: [\"http\", \"https\", \"mailto\"] },\n};\n\nexport interface DirectiveExtensionOptions {\n readonly name: string;\n readonly label?: string;\n readonly className?: string;\n readonly version?: string;\n}\n\nfunction directiveName(value: string): string {\n if (!/^[a-z][a-z0-9-]*$/.test(value)) throw new TypeError(`MDFN_DIRECTIVE_NAME_INVALID:${value}`);\n return value;\n}\n\nexport function createDirectiveExtension(options: DirectiveExtensionOptions): MdfnExtension {\n const name = directiveName(options.name);\n const nodeType = `directive-${name}`;\n return {\n name: `directive/${name}`,\n version: options.version ?? \"1.0.0\",\n dependencies: [\"commonmark\"],\n schema: { nodes: [nodeType] },\n preservation: exactPreservation,\n security: { allowsRawHtml: false },\n parseMarkdown({ source, offset, line }) {\n const opening = new RegExp(`^(:{3,})[ \\\\t]*${name}(?:[ \\\\t]+([^\\\\r\\\\n]*?))?[ \\\\t]*(?:\\\\r?\\\\n|\\\\r|$)`).exec(line);\n if (!opening) return null;\n const searchFrom = offset + line.length;\n const closePattern = new RegExp(`^:{${opening[1].length},}[ \\\\t]*(?:\\\\r?\\\\n|\\\\r|$)`, \"gm\");\n closePattern.lastIndex = searchFrom;\n const close = closePattern.exec(source);\n const closeEnd = close ? close.index + close[0].length : source.length;\n const bodyEnd = close?.index ?? source.length;\n const body = source.slice(searchFrom, bodyEnd).replace(/\\r?\\n$/, \"\");\n return {\n consumed: closeEnd - offset,\n node: {\n type: nodeType,\n attrs: { name, label: opening[2]?.trim() || options.label || name },\n text: body,\n },\n diagnostics: close ? [] : [{ code: \"MDFN_DIRECTIVE_UNCLOSED\", message: `Directive ${name} has no closing fence`, severity: \"warning\", source: { from: offset, to: source.length }, extension: `directive/${name}` }],\n };\n },\n serializeMarkdown({ node }) {\n if (node.type !== nodeType) return null;\n const label = typeof node.attrs?.label === \"string\" && node.attrs.label !== name ? ` ${node.attrs.label}` : \"\";\n const body = node.text ?? \"\";\n let fenceLength = 3;\n for (const match of body.matchAll(/^(:{3,})[ \\\\t]*(?:\\\\r)?$/gm)) fenceLength = Math.max(fenceLength, match[1].length + 1);\n const fence = \":\".repeat(fenceLength);\n return `${fence}${name}${label}\\n${body}\\n${fence}`;\n },\n render({ node }) {\n if (node.type !== nodeType) return null;\n const label = typeof node.attrs?.label === \"string\" ? node.attrs.label : options.label ?? name;\n const classes = [\"mdfn-directive\", `mdfn-directive-${name}`, options.className].filter(Boolean).join(\" \");\n return {\n tag: \"aside\",\n attrs: { class: classes, \"data-md-directive\": name },\n children: [\n { tag: \"strong\", text: label },\n { tag: \"p\", text: node.text ?? \"\" },\n ],\n };\n },\n visual({ node }) {\n if (node.type !== nodeType) return null;\n const label = typeof node.attrs?.label === \"string\" ? node.attrs.label : options.label ?? name;\n return {\n tag: \"aside\",\n attrs: { class: \"mdfn-directive-visual\", \"data-md-directive\": name },\n children: [\n { tag: \"strong\", text: label },\n { tag: \"p\", text: node.text ?? \"\" },\n ],\n };\n },\n diagnostics(document) {\n const diagnostics: Array<{ code: string; message: string; severity: \"warning\"; nodeId?: string; extension: string }> = [];\n const visit = (node: MdfnNode): void => {\n if (node.type === nodeType && !(node.text ?? \"\").trim()) diagnostics.push({ code: \"MDFN_DIRECTIVE_EMPTY\", message: `Directive ${name} is empty`, severity: \"warning\", nodeId: node.id, extension: `directive/${name}` });\n node.content?.forEach(visit);\n };\n visit(document);\n return diagnostics;\n },\n migrations: [{\n from: 1,\n to: 2,\n migrate(document: MdfnDocument): MdfnDocument {\n const migrate = (node: MdfnNode): MdfnNode => node.type === `callout-${name}`\n ? { ...node, type: nodeType }\n : { ...node, content: node.content?.map(migrate) };\n return { ...migrate(document), type: \"doc\", schemaVersion: 2 } as MdfnDocument;\n },\n }],\n certification: {\n schemaVersion: 1,\n fixtures: [`directive-${name}`],\n capabilities: [\"parse\", \"serialize\", \"render\", \"visual\", \"diagnostics\", \"migrations\", \"security\"],\n },\n };\n}\n\nexport const calloutExtension = createDirectiveExtension({ name: \"callout\", label: \"Callout\" });\nexport const diagramExtension = createDirectiveExtension({ name: \"diagram\", label: \"Diagram\" });\n\nexport const defaultExtensions = Object.freeze([commonmarkExtension, gfmExtension]);\nexport const authoringExtensions = Object.freeze([commonmarkExtension, gfmExtension, calloutExtension, diagramExtension]);\n\nexport const MDFN_EXTENSIONS_VERSION = \"0.1.0\" as const;\n"],"mappings":"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","names":[]}
@@ -0,0 +1,153 @@
1
+ "use strict";
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __export = (target, all) => {
7
+ for (var name in all)
8
+ __defProp(target, name, { get: all[name], enumerable: true });
9
+ };
10
+ var __copyProps = (to, from, except, desc) => {
11
+ if (from && typeof from === "object" || typeof from === "function") {
12
+ for (let key of __getOwnPropNames(from))
13
+ if (!__hasOwnProp.call(to, key) && key !== except)
14
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
+ }
16
+ return to;
17
+ };
18
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
+
20
+ // src/commonmark.ts
21
+ var commonmark_exports = {};
22
+ __export(commonmark_exports, {
23
+ commonmarkExtension: () => commonmarkExtension
24
+ });
25
+ module.exports = __toCommonJS(commonmark_exports);
26
+
27
+ // src/index.ts
28
+ var exactPreservation = {
29
+ noEdit: "exact",
30
+ edited: "touched-region",
31
+ unsupported: "opaque"
32
+ };
33
+ var commonmarkExtension = {
34
+ name: "commonmark",
35
+ version: "1.0.0",
36
+ schema: {
37
+ nodes: ["doc", "paragraph", "heading", "blockquote", "list", "listItem", "codeBlock", "inlineCode", "thematicBreak", "hardBreak", "text", "strong", "emphasis", "link", "image", "opaque"],
38
+ marks: ["strong", "emphasis", "code", "link"]
39
+ },
40
+ preservation: exactPreservation,
41
+ security: { allowsRawHtml: false, urlSchemes: ["http", "https", "mailto"] }
42
+ };
43
+ var gfmExtension = {
44
+ name: "gfm",
45
+ version: "1.0.0",
46
+ dependencies: ["commonmark"],
47
+ schema: { nodes: ["table", "tableRow", "tableCell", "taskListItem", "delete"], marks: ["delete"] },
48
+ preservation: exactPreservation,
49
+ security: { allowsRawHtml: false, urlSchemes: ["http", "https", "mailto"] }
50
+ };
51
+ function directiveName(value) {
52
+ if (!/^[a-z][a-z0-9-]*$/.test(value)) throw new TypeError(`MDFN_DIRECTIVE_NAME_INVALID:${value}`);
53
+ return value;
54
+ }
55
+ function createDirectiveExtension(options) {
56
+ const name = directiveName(options.name);
57
+ const nodeType = `directive-${name}`;
58
+ return {
59
+ name: `directive/${name}`,
60
+ version: options.version ?? "1.0.0",
61
+ dependencies: ["commonmark"],
62
+ schema: { nodes: [nodeType] },
63
+ preservation: exactPreservation,
64
+ security: { allowsRawHtml: false },
65
+ parseMarkdown({ source, offset, line }) {
66
+ const opening = new RegExp(`^(:{3,})[ \\t]*${name}(?:[ \\t]+([^\\r\\n]*?))?[ \\t]*(?:\\r?\\n|\\r|$)`).exec(line);
67
+ if (!opening) return null;
68
+ const searchFrom = offset + line.length;
69
+ const closePattern = new RegExp(`^:{${opening[1].length},}[ \\t]*(?:\\r?\\n|\\r|$)`, "gm");
70
+ closePattern.lastIndex = searchFrom;
71
+ const close = closePattern.exec(source);
72
+ const closeEnd = close ? close.index + close[0].length : source.length;
73
+ const bodyEnd = close?.index ?? source.length;
74
+ const body = source.slice(searchFrom, bodyEnd).replace(/\r?\n$/, "");
75
+ return {
76
+ consumed: closeEnd - offset,
77
+ node: {
78
+ type: nodeType,
79
+ attrs: { name, label: opening[2]?.trim() || options.label || name },
80
+ text: body
81
+ },
82
+ diagnostics: close ? [] : [{ code: "MDFN_DIRECTIVE_UNCLOSED", message: `Directive ${name} has no closing fence`, severity: "warning", source: { from: offset, to: source.length }, extension: `directive/${name}` }]
83
+ };
84
+ },
85
+ serializeMarkdown({ node }) {
86
+ if (node.type !== nodeType) return null;
87
+ const label = typeof node.attrs?.label === "string" && node.attrs.label !== name ? ` ${node.attrs.label}` : "";
88
+ const body = node.text ?? "";
89
+ let fenceLength = 3;
90
+ for (const match of body.matchAll(/^(:{3,})[ \\t]*(?:\\r)?$/gm)) fenceLength = Math.max(fenceLength, match[1].length + 1);
91
+ const fence = ":".repeat(fenceLength);
92
+ return `${fence}${name}${label}
93
+ ${body}
94
+ ${fence}`;
95
+ },
96
+ render({ node }) {
97
+ if (node.type !== nodeType) return null;
98
+ const label = typeof node.attrs?.label === "string" ? node.attrs.label : options.label ?? name;
99
+ const classes = ["mdfn-directive", `mdfn-directive-${name}`, options.className].filter(Boolean).join(" ");
100
+ return {
101
+ tag: "aside",
102
+ attrs: { class: classes, "data-md-directive": name },
103
+ children: [
104
+ { tag: "strong", text: label },
105
+ { tag: "p", text: node.text ?? "" }
106
+ ]
107
+ };
108
+ },
109
+ visual({ node }) {
110
+ if (node.type !== nodeType) return null;
111
+ const label = typeof node.attrs?.label === "string" ? node.attrs.label : options.label ?? name;
112
+ return {
113
+ tag: "aside",
114
+ attrs: { class: "mdfn-directive-visual", "data-md-directive": name },
115
+ children: [
116
+ { tag: "strong", text: label },
117
+ { tag: "p", text: node.text ?? "" }
118
+ ]
119
+ };
120
+ },
121
+ diagnostics(document) {
122
+ const diagnostics = [];
123
+ const visit = (node) => {
124
+ if (node.type === nodeType && !(node.text ?? "").trim()) diagnostics.push({ code: "MDFN_DIRECTIVE_EMPTY", message: `Directive ${name} is empty`, severity: "warning", nodeId: node.id, extension: `directive/${name}` });
125
+ node.content?.forEach(visit);
126
+ };
127
+ visit(document);
128
+ return diagnostics;
129
+ },
130
+ migrations: [{
131
+ from: 1,
132
+ to: 2,
133
+ migrate(document) {
134
+ const migrate = (node) => node.type === `callout-${name}` ? { ...node, type: nodeType } : { ...node, content: node.content?.map(migrate) };
135
+ return { ...migrate(document), type: "doc", schemaVersion: 2 };
136
+ }
137
+ }],
138
+ certification: {
139
+ schemaVersion: 1,
140
+ fixtures: [`directive-${name}`],
141
+ capabilities: ["parse", "serialize", "render", "visual", "diagnostics", "migrations", "security"]
142
+ }
143
+ };
144
+ }
145
+ var calloutExtension = createDirectiveExtension({ name: "callout", label: "Callout" });
146
+ var diagramExtension = createDirectiveExtension({ name: "diagram", label: "Diagram" });
147
+ var defaultExtensions = Object.freeze([commonmarkExtension, gfmExtension]);
148
+ var authoringExtensions = Object.freeze([commonmarkExtension, gfmExtension, calloutExtension, diagramExtension]);
149
+ // Annotate the CommonJS export names for ESM import in node:
150
+ 0 && (module.exports = {
151
+ commonmarkExtension
152
+ });
153
+ //# sourceMappingURL=commonmark.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/commonmark.ts","../src/index.ts"],"sourcesContent":["export { commonmarkExtension } from \"./index\";\n","import type { MdfnDocument, MdfnExtension, MdfnNode } from \"@mdfn/core\";\n\nconst exactPreservation = {\n noEdit: \"exact\",\n edited: \"touched-region\",\n unsupported: \"opaque\",\n} as const;\n\nexport const commonmarkExtension: MdfnExtension = {\n name: \"commonmark\",\n version: \"1.0.0\",\n schema: {\n nodes: [\"doc\", \"paragraph\", \"heading\", \"blockquote\", \"list\", \"listItem\", \"codeBlock\", \"inlineCode\", \"thematicBreak\", \"hardBreak\", \"text\", \"strong\", \"emphasis\", \"link\", \"image\", \"opaque\"],\n marks: [\"strong\", \"emphasis\", \"code\", \"link\"],\n },\n preservation: exactPreservation,\n security: { allowsRawHtml: false, urlSchemes: [\"http\", \"https\", \"mailto\"] },\n};\n\nexport const gfmExtension: MdfnExtension = {\n name: \"gfm\",\n version: \"1.0.0\",\n dependencies: [\"commonmark\"],\n schema: { nodes: [\"table\", \"tableRow\", \"tableCell\", \"taskListItem\", \"delete\"], marks: [\"delete\"] },\n preservation: exactPreservation,\n security: { allowsRawHtml: false, urlSchemes: [\"http\", \"https\", \"mailto\"] },\n};\n\nexport interface DirectiveExtensionOptions {\n readonly name: string;\n readonly label?: string;\n readonly className?: string;\n readonly version?: string;\n}\n\nfunction directiveName(value: string): string {\n if (!/^[a-z][a-z0-9-]*$/.test(value)) throw new TypeError(`MDFN_DIRECTIVE_NAME_INVALID:${value}`);\n return value;\n}\n\nexport function createDirectiveExtension(options: DirectiveExtensionOptions): MdfnExtension {\n const name = directiveName(options.name);\n const nodeType = `directive-${name}`;\n return {\n name: `directive/${name}`,\n version: options.version ?? \"1.0.0\",\n dependencies: [\"commonmark\"],\n schema: { nodes: [nodeType] },\n preservation: exactPreservation,\n security: { allowsRawHtml: false },\n parseMarkdown({ source, offset, line }) {\n const opening = new RegExp(`^(:{3,})[ \\\\t]*${name}(?:[ \\\\t]+([^\\\\r\\\\n]*?))?[ \\\\t]*(?:\\\\r?\\\\n|\\\\r|$)`).exec(line);\n if (!opening) return null;\n const searchFrom = offset + line.length;\n const closePattern = new RegExp(`^:{${opening[1].length},}[ \\\\t]*(?:\\\\r?\\\\n|\\\\r|$)`, \"gm\");\n closePattern.lastIndex = searchFrom;\n const close = closePattern.exec(source);\n const closeEnd = close ? close.index + close[0].length : source.length;\n const bodyEnd = close?.index ?? source.length;\n const body = source.slice(searchFrom, bodyEnd).replace(/\\r?\\n$/, \"\");\n return {\n consumed: closeEnd - offset,\n node: {\n type: nodeType,\n attrs: { name, label: opening[2]?.trim() || options.label || name },\n text: body,\n },\n diagnostics: close ? [] : [{ code: \"MDFN_DIRECTIVE_UNCLOSED\", message: `Directive ${name} has no closing fence`, severity: \"warning\", source: { from: offset, to: source.length }, extension: `directive/${name}` }],\n };\n },\n serializeMarkdown({ node }) {\n if (node.type !== nodeType) return null;\n const label = typeof node.attrs?.label === \"string\" && node.attrs.label !== name ? ` ${node.attrs.label}` : \"\";\n const body = node.text ?? \"\";\n let fenceLength = 3;\n for (const match of body.matchAll(/^(:{3,})[ \\\\t]*(?:\\\\r)?$/gm)) fenceLength = Math.max(fenceLength, match[1].length + 1);\n const fence = \":\".repeat(fenceLength);\n return `${fence}${name}${label}\\n${body}\\n${fence}`;\n },\n render({ node }) {\n if (node.type !== nodeType) return null;\n const label = typeof node.attrs?.label === \"string\" ? node.attrs.label : options.label ?? name;\n const classes = [\"mdfn-directive\", `mdfn-directive-${name}`, options.className].filter(Boolean).join(\" \");\n return {\n tag: \"aside\",\n attrs: { class: classes, \"data-md-directive\": name },\n children: [\n { tag: \"strong\", text: label },\n { tag: \"p\", text: node.text ?? \"\" },\n ],\n };\n },\n visual({ node }) {\n if (node.type !== nodeType) return null;\n const label = typeof node.attrs?.label === \"string\" ? node.attrs.label : options.label ?? name;\n return {\n tag: \"aside\",\n attrs: { class: \"mdfn-directive-visual\", \"data-md-directive\": name },\n children: [\n { tag: \"strong\", text: label },\n { tag: \"p\", text: node.text ?? \"\" },\n ],\n };\n },\n diagnostics(document) {\n const diagnostics: Array<{ code: string; message: string; severity: \"warning\"; nodeId?: string; extension: string }> = [];\n const visit = (node: MdfnNode): void => {\n if (node.type === nodeType && !(node.text ?? \"\").trim()) diagnostics.push({ code: \"MDFN_DIRECTIVE_EMPTY\", message: `Directive ${name} is empty`, severity: \"warning\", nodeId: node.id, extension: `directive/${name}` });\n node.content?.forEach(visit);\n };\n visit(document);\n return diagnostics;\n },\n migrations: [{\n from: 1,\n to: 2,\n migrate(document: MdfnDocument): MdfnDocument {\n const migrate = (node: MdfnNode): MdfnNode => node.type === `callout-${name}`\n ? { ...node, type: nodeType }\n : { ...node, content: node.content?.map(migrate) };\n return { ...migrate(document), type: \"doc\", schemaVersion: 2 } as MdfnDocument;\n },\n }],\n certification: {\n schemaVersion: 1,\n fixtures: [`directive-${name}`],\n capabilities: [\"parse\", \"serialize\", \"render\", \"visual\", \"diagnostics\", \"migrations\", \"security\"],\n },\n };\n}\n\nexport const calloutExtension = createDirectiveExtension({ name: \"callout\", label: \"Callout\" });\nexport const diagramExtension = createDirectiveExtension({ name: \"diagram\", label: \"Diagram\" });\n\nexport const defaultExtensions = Object.freeze([commonmarkExtension, gfmExtension]);\nexport const authoringExtensions = Object.freeze([commonmarkExtension, gfmExtension, calloutExtension, diagramExtension]);\n\nexport const MDFN_EXTENSIONS_VERSION = \"0.1.0\" as const;\n"],"mappings":"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","names":[]}
@@ -0,0 +1,2 @@
1
+ export { commonmarkExtension } from './index.cjs';
2
+ import '@mdfn/core';
@@ -0,0 +1,2 @@
1
+ export { commonmarkExtension } from './index.js';
2
+ import '@mdfn/core';
@@ -0,0 +1,7 @@
1
+ import {
2
+ commonmarkExtension
3
+ } from "./chunk-4I3JGYQE.js";
4
+ export {
5
+ commonmarkExtension
6
+ };
7
+ //# sourceMappingURL=commonmark.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":[],"sourcesContent":[],"mappings":"","names":[]}