@wgtechlabs/mdd-engine 0.1.0-pr.cab0713 → 0.1.0-pr.d58d6d6

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 CHANGED
@@ -84,16 +84,19 @@ order: 1
84
84
  ---
85
85
  # Installation
86
86
 
87
- :::note[Before you start]
88
- You need a local documentation project.
89
- :::
87
+ > [!NOTE]
88
+ > **Before you start**
89
+ >
90
+ > You need a local documentation project.
90
91
 
91
92
  :::details[More information]
92
93
  Ordinary **Markdown** works inside components.
93
94
  :::
94
95
  ```
95
96
 
96
- Use `note`, `tip`, `warning`, or `details` containers. Labels are optional; attributes and unknown component names are errors. Callouts become semantic `aside` elements, disclosures become `details`/`summary`, and each has a stable `mdd-<component>` class. Readable Markdown uses blockquotes with bold labels, without executable content.
97
+ Use GitHub-style alerts with `NOTE`, `TIP`, `IMPORTANT`, `WARNING`, or `CAUTION`. Put the exact uppercase marker on the opening line of a blockquote at the document root; nested blockquotes remain ordinary quotes. Alerts become semantic `aside` elements with `mdd-alert` and `mdd-<type>` classes. Their readable Markdown preserves the `> [!TYPE]` marker. The engine supplies meaning and labels; the reader composes the article, and themes supply icons and colors.
98
+
99
+ `:::details[More information]` remains supported and becomes `details`/`summary`; its label is optional, attributes are errors, and its readable Markdown uses a blockquote with a bold label. The old `:::note`, `:::tip`, and `:::warning` directives now fail with a `REMOVED_COMPONENT` migration diagnostic. See [alerts and migration](docs/ALERTS.md) for all five types, theme hooks, and how to preserve custom titles and bodies.
97
100
 
98
101
  Title precedence is frontmatter title, first H1, then readable filename. Navigation uses `navTitle` when supplied. Explicit `order` sorts first; remaining siblings sort deterministically by label and path.
99
102
 
@@ -0,0 +1,8 @@
1
+ import type { Root } from "mdast";
2
+ declare module "mdast" {
3
+ interface TextData {
4
+ mddAlertMarker?: true;
5
+ }
6
+ }
7
+ /** Recognize alerts only at the document root, using unescaped source syntax. */
8
+ export declare function transformAlerts(tree: Root, source: string): void;
package/dist/alerts.js ADDED
@@ -0,0 +1,56 @@
1
+ /** Recognize alerts only at the document root, using unescaped source syntax. */
2
+ export function transformAlerts(tree, source) {
3
+ for (const node of tree.children) {
4
+ if (node.type !== "blockquote")
5
+ continue;
6
+ const paragraph = node.children[0];
7
+ const first = paragraph?.type === "paragraph" ? paragraph.children[0] : undefined;
8
+ const offset = paragraph?.position?.start.offset;
9
+ if (paragraph?.type !== "paragraph" ||
10
+ first?.type !== "text" ||
11
+ offset === undefined ||
12
+ paragraph.position?.start.line !== node.position?.start.line)
13
+ continue;
14
+ const marker = /^\[!(NOTE|TIP|IMPORTANT|WARNING|CAUTION)\][\t ]*(?:\r\n|\r|\n|$)/.exec(source.slice(offset));
15
+ const kind = marker?.[1];
16
+ if (!kind)
17
+ continue;
18
+ first.value = first.value.slice(kind.length + 3);
19
+ const bodyStart = paragraph.children[0];
20
+ if (bodyStart?.type === "text") {
21
+ bodyStart.value = bodyStart.value.replace(/^[\t ]*(?:\r\n|\r|\n)?/, "");
22
+ if (!bodyStart.value)
23
+ paragraph.children.shift();
24
+ }
25
+ if (paragraph.children[0]?.type === "break")
26
+ paragraph.children.shift();
27
+ if (!paragraph.children.length)
28
+ node.children.shift();
29
+ const type = kind.toLowerCase();
30
+ const label = type.charAt(0).toUpperCase() + type.slice(1);
31
+ const markerText = {
32
+ type: "text",
33
+ value: `[!${kind}]`,
34
+ data: { mddAlertMarker: true },
35
+ };
36
+ node.children.unshift({
37
+ type: "paragraph",
38
+ children: [markerText],
39
+ data: {
40
+ hProperties: { className: ["mdd-component-label"] },
41
+ hChildren: [
42
+ {
43
+ type: "element",
44
+ tagName: "strong",
45
+ properties: {},
46
+ children: [{ type: "text", value: label }],
47
+ },
48
+ ],
49
+ },
50
+ });
51
+ node.data = {
52
+ hName: "aside",
53
+ hProperties: { className: ["mdd-alert", `mdd-${type}`] },
54
+ };
55
+ }
56
+ }
package/dist/markdown.js CHANGED
@@ -12,6 +12,7 @@ import remarkStringify from "remark-stringify";
12
12
  import { unified } from "unified";
13
13
  import { SKIP, visit } from "unist-util-visit";
14
14
  import { parseDocument as parseYaml } from "yaml";
15
+ import { transformAlerts } from "./alerts.js";
15
16
  const parser = unified()
16
17
  .use(remarkParse)
17
18
  .use(remarkGfm)
@@ -44,8 +45,19 @@ const htmlRenderer = unified()
44
45
  },
45
46
  })
46
47
  .use(rehypeStringify);
47
- const markdownRenderer = unified().use(remarkGfm).use(remarkStringify);
48
- const componentNames = new Set(["note", "tip", "warning", "details"]);
48
+ const markdownRenderer = unified()
49
+ .use(remarkGfm)
50
+ .use(remarkStringify, {
51
+ handlers: {
52
+ text(node, _parent, state, info) {
53
+ // Only generated alert markers bypass normal Markdown escaping.
54
+ return node.data?.mddAlertMarker === true
55
+ ? node.value
56
+ : state.safe(node.value, info);
57
+ },
58
+ },
59
+ });
60
+ const removedNotices = new Set(["note", "tip", "warning"]);
49
61
  /** Keep the same first-wins, reachable definitions that the HTML renderer uses. */
50
62
  function retainReferencedDefinitions(tree) {
51
63
  const definitions = new Map();
@@ -100,6 +112,7 @@ function unsafeUrl(url, image) {
100
112
  }
101
113
  export function parseDocument(source, file, diagnostics) {
102
114
  const tree = parser.parse(source);
115
+ transformAlerts(tree, source);
103
116
  retainReferencedDefinitions(tree);
104
117
  const metadata = {};
105
118
  const headings = [];
@@ -185,8 +198,12 @@ export function parseDocument(source, file, diagnostics) {
185
198
  node.type !== "textDirective") {
186
199
  return;
187
200
  }
188
- if (node.type !== "containerDirective" || !componentNames.has(node.name)) {
189
- report("UNKNOWN_COMPONENT", `Unsupported component ${node.name}; use a note, tip, warning, or details container.`, node);
201
+ if (removedNotices.has(node.name)) {
202
+ report("REMOVED_COMPONENT", `The ${node.name} directive was removed; use > [!${node.name.toUpperCase()}] followed by quoted body lines. Keep any optional custom title as bold text in the alert body.`, node);
203
+ return;
204
+ }
205
+ if (node.type !== "containerDirective" || node.name !== "details") {
206
+ report("UNKNOWN_COMPONENT", `Unsupported component ${node.name}; use a GitHub alert or a details container.`, node);
190
207
  return;
191
208
  }
192
209
  if (Object.keys(node.attributes ?? {}).length) {
@@ -195,7 +212,7 @@ export function parseDocument(source, file, diagnostics) {
195
212
  if (index === undefined || !parent)
196
213
  return;
197
214
  const first = node.children[0];
198
- const defaultLabel = node.name.charAt(0).toUpperCase() + node.name.slice(1);
215
+ const defaultLabel = "Details";
199
216
  const label = first?.type === "paragraph" && first.data?.directiveLabel
200
217
  ? first
201
218
  : {
@@ -214,7 +231,7 @@ export function parseDocument(source, file, diagnostics) {
214
231
  }
215
232
  label.children = [{ type: "strong", children: label.children }];
216
233
  label.data = {
217
- hName: node.name === "details" ? "summary" : "p",
234
+ hName: "summary",
218
235
  hProperties: { className: ["mdd-component-label"] },
219
236
  };
220
237
  parent.children[index] = {
@@ -222,8 +239,8 @@ export function parseDocument(source, file, diagnostics) {
222
239
  children: node.children,
223
240
  position: node.position,
224
241
  data: {
225
- hName: node.name === "details" ? "details" : "aside",
226
- hProperties: { className: [`mdd-${node.name}`] },
242
+ hName: "details",
243
+ hProperties: { className: ["mdd-details"] },
227
244
  },
228
245
  };
229
246
  // Revisit the replacement so nested content is validated exactly once.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@wgtechlabs/mdd-engine",
3
- "version": "0.1.0-pr.cab0713",
3
+ "version": "0.1.0-pr.d58d6d6",
4
4
  "description": "Headless Markdown documentation compiler for mdd",
5
5
  "type": "module",
6
6
  "license": "MIT",