remark-mdat 2.0.0-preview.2 → 2.0.0-preview.4
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 +8 -3
- package/dist/index.js +20 -7
- package/package.json +3 -3
- package/readme.md +127 -14
package/dist/index.d.ts
CHANGED
|
@@ -167,10 +167,15 @@ declare function getMdatReports(files: VFile[]): MdatFileReport[];
|
|
|
167
167
|
declare function reporterMdat(files: VFile[]): void;
|
|
168
168
|
//#endregion
|
|
169
169
|
//#region src/lib/remark-mdat.d.ts
|
|
170
|
-
type Options =
|
|
170
|
+
type Options = {
|
|
171
|
+
rules?: Rules;
|
|
172
|
+
};
|
|
173
|
+
declare const optionsSchema: z.ZodObject<{
|
|
174
|
+
rules: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodType<unknown, unknown, z.core.$ZodTypeInternals<unknown, unknown>>>>;
|
|
175
|
+
}, z.core.$strip>;
|
|
171
176
|
/**
|
|
172
177
|
* A remark plugin that expands HTML comments in Markdown files.
|
|
173
178
|
*/
|
|
174
|
-
declare const remarkMdat: Plugin<[Options], Root>;
|
|
179
|
+
declare const remarkMdat: Plugin<[Options?], Root>;
|
|
175
180
|
//#endregion
|
|
176
|
-
export { type MdatFileReport, type MdatMessage, type NormalizedRule, type NormalizedRules, type Options, type Rule, type RuleContext, type Rules, type SimplifyDeep, remarkMdat as default, getMdatReports, getSoleRule, getSoleRuleKey, mdat, mdatClean, mdatExpand, mdatSplit,
|
|
181
|
+
export { type MdatFileReport, type MdatMessage, type NormalizedRule, type NormalizedRules, type Options, type Rule, type RuleContext, type Rules, type SimplifyDeep, remarkMdat as default, getMdatReports, getSoleRule, getSoleRuleKey, mdat, mdatClean, mdatExpand, mdatSplit, optionsSchema, reporterMdat, rulesSchema, setLogger };
|
package/dist/index.js
CHANGED
|
@@ -276,15 +276,25 @@ const keywordSchema = z.string().check(z.refine((key) => !/^[/*#]/.test(key), {
|
|
|
276
276
|
const rulesSchema = z.record(keywordSchema, ruleSchema).describe("MDAT Rules");
|
|
277
277
|
const normalizedRulesSchema = z.record(keywordSchema, normalizedRuleSchema).describe("MDAT Rules");
|
|
278
278
|
/**
|
|
279
|
-
*
|
|
279
|
+
* Expand rule content. For compound rules (content arrays), individual
|
|
280
|
+
* sub-rule failures are reported via `onWarning` and skipped. The entire
|
|
281
|
+
* expansion only fails if every sub-rule fails.
|
|
280
282
|
*/
|
|
281
|
-
async function getRuleContent(rule, options, context) {
|
|
283
|
+
async function getRuleContent(rule, options, context, onWarning) {
|
|
282
284
|
if (Array.isArray(rule.content)) {
|
|
283
285
|
const subruleContent = [];
|
|
286
|
+
const errors = [];
|
|
284
287
|
for (const [index, subrule] of rule.content.entries()) {
|
|
285
288
|
const subruleOptions = Array.isArray(options) ? options.at(index) : void 0;
|
|
286
|
-
|
|
289
|
+
try {
|
|
290
|
+
subruleContent.push(await getRuleContent(subrule, subruleOptions ?? {}, context, onWarning));
|
|
291
|
+
} catch (error) {
|
|
292
|
+
const message = error instanceof Error ? error.cause instanceof Error ? error.cause.message : error.message : String(error);
|
|
293
|
+
onWarning?.(`Sub-rule ${String(index)} failed: ${message}`);
|
|
294
|
+
errors.push(error instanceof Error ? error : new Error(String(error)));
|
|
295
|
+
}
|
|
287
296
|
}
|
|
297
|
+
if (subruleContent.length === 0) throw new AggregateError(errors, "All sub-rules failed in compound rule");
|
|
288
298
|
return subruleContent.join("\n\n");
|
|
289
299
|
}
|
|
290
300
|
try {
|
|
@@ -363,7 +373,9 @@ async function mdatExpand(tree, file, rules) {
|
|
|
363
373
|
const rule = normalizedRules[keyword];
|
|
364
374
|
let newMarkdownString = "";
|
|
365
375
|
try {
|
|
366
|
-
newMarkdownString = await getRuleContent(rule, options, context)
|
|
376
|
+
newMarkdownString = await getRuleContent(rule, options, context, (warning) => {
|
|
377
|
+
saveLog(file, "warn", "expand", `${html}: ${warning}`, node);
|
|
378
|
+
});
|
|
367
379
|
if (newMarkdownString.trim() === "") saveLog(file, "error", "expand", `Got empty content when expanding ${html}`, node);
|
|
368
380
|
} catch (error) {
|
|
369
381
|
if (error instanceof Error) {
|
|
@@ -454,17 +466,18 @@ async function mdat(tree, file, rules) {
|
|
|
454
466
|
//#endregion
|
|
455
467
|
//#region src/lib/remark-mdat.ts
|
|
456
468
|
const defaultRules = { mdat: `Powered by the Markdown Autophagic Template system: [mdat](https://github.com/kitschpatrol/mdat).` };
|
|
469
|
+
const optionsSchema = z.object({ rules: rulesSchema.optional() }).describe("MDAT Plugin Options");
|
|
457
470
|
/**
|
|
458
471
|
* A remark plugin that expands HTML comments in Markdown files.
|
|
459
472
|
*/
|
|
460
|
-
const remarkMdat = function(
|
|
473
|
+
const remarkMdat = function(options) {
|
|
461
474
|
const resolvedRules = {
|
|
462
475
|
...defaultRules,
|
|
463
|
-
...rules
|
|
476
|
+
...options?.rules
|
|
464
477
|
};
|
|
465
478
|
return async function(tree, file) {
|
|
466
479
|
await mdat(tree, file, resolvedRules);
|
|
467
480
|
};
|
|
468
481
|
};
|
|
469
482
|
//#endregion
|
|
470
|
-
export { remarkMdat as default, getMdatReports, getSoleRule, getSoleRuleKey, mdat, mdatClean, mdatExpand, mdatSplit,
|
|
483
|
+
export { remarkMdat as default, getMdatReports, getSoleRule, getSoleRuleKey, mdat, mdatClean, mdatExpand, mdatSplit, optionsSchema, reporterMdat, rulesSchema, setLogger };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "remark-mdat",
|
|
3
|
-
"version": "2.0.0-preview.
|
|
3
|
+
"version": "2.0.0-preview.4",
|
|
4
4
|
"description": "A remark plugin implementing the Markdown Autophagic Template (MDAT) system.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"mdat",
|
|
@@ -63,9 +63,9 @@
|
|
|
63
63
|
"@types/node": "~20.19.37",
|
|
64
64
|
"bumpp": "^11.0.1",
|
|
65
65
|
"publint": "^0.3.18",
|
|
66
|
-
"tsdown": "^0.21.
|
|
66
|
+
"tsdown": "^0.21.7",
|
|
67
67
|
"typescript": "~5.9.3",
|
|
68
|
-
"vitest": "^4.1.
|
|
68
|
+
"vitest": "^4.1.2"
|
|
69
69
|
},
|
|
70
70
|
"engines": {
|
|
71
71
|
"node": ">=20.19.6"
|
package/readme.md
CHANGED
|
@@ -41,6 +41,7 @@
|
|
|
41
41
|
- [API](#api)
|
|
42
42
|
- [Examples](#examples)
|
|
43
43
|
- [Utilities](#utilities)
|
|
44
|
+
- [Migrating from remark-mdat 1.x to 2.x](#migrating-from-remark-mdat-1x-to-2x)
|
|
44
45
|
- [Implementation notes](#implementation-notes)
|
|
45
46
|
- [Maintainers](#maintainers)
|
|
46
47
|
- [Acknowledgments](#acknowledgments)
|
|
@@ -53,13 +54,13 @@
|
|
|
53
54
|
|
|
54
55
|
This is a [remark](https://remark.js.org) plugin that automates the inline expansion of placeholder HTML comments with dynamic content in Markdown, making it easy to keep readme files and other documentation in sync with an external single source of truth.
|
|
55
56
|
|
|
56
|
-
The plugin
|
|
57
|
+
The plugin finds placeholder comments in a Markdown file like this:
|
|
57
58
|
|
|
58
59
|
```md
|
|
59
60
|
<!-- title -->
|
|
60
61
|
```
|
|
61
62
|
|
|
62
|
-
And
|
|
63
|
+
And expands them with the data of your choosing. In this case, it reads the `title` field a nearby `package.json`:
|
|
63
64
|
|
|
64
65
|
```md
|
|
65
66
|
<!-- title -->
|
|
@@ -75,12 +76,12 @@ This plugin powers the higher-level [`mdat` package](https://github.com/kitschpa
|
|
|
75
76
|
|
|
76
77
|
### Dependencies
|
|
77
78
|
|
|
78
|
-
This library is ESM only and requires Node 20+. It's designed to work with Remark 15. `remark-mdat` is implemented in TypeScript and bundles a complete set of type definitions.
|
|
79
|
+
This library is ESM only and requires Node 20.19.6+. It's designed to work with Remark 15. `remark-mdat` is implemented in TypeScript and bundles a complete set of type definitions.
|
|
79
80
|
|
|
80
81
|
### Installation
|
|
81
82
|
|
|
82
83
|
```sh
|
|
83
|
-
|
|
84
|
+
pnpm add remark-mdat
|
|
84
85
|
```
|
|
85
86
|
|
|
86
87
|
## Usage
|
|
@@ -102,7 +103,7 @@ remark().use(remarkMdat)
|
|
|
102
103
|
|
|
103
104
|
#### Options
|
|
104
105
|
|
|
105
|
-
The plugin accepts an optional `
|
|
106
|
+
The plugin accepts an optional `Options` object with a `rules` field. `Rules` is a `Record<string, Rule>` where each key is a keyword matching an HTML comment in the Markdown file (e.g. `title` matches `<!-- title -->`).
|
|
106
107
|
|
|
107
108
|
HTML comments using code-style notation (`<!-- // ... -->`, `<!-- # ... -->`, `<!-- /* ... */ -->`) are ignored and will not be treated as mdat keywords. Rule keywords cannot start with `/`, `*`, or `#`.
|
|
108
109
|
|
|
@@ -119,9 +120,9 @@ const rules: Rules = {
|
|
|
119
120
|
// Function with arguments: receives parsed options from the comment
|
|
120
121
|
personalGreeting: (options) => `Hello, ${options.name}!`,
|
|
121
122
|
|
|
122
|
-
// Object:
|
|
123
|
+
// Object: with processing priority
|
|
123
124
|
title: {
|
|
124
|
-
order:
|
|
125
|
+
order: 1, // Runs after other rules (default is 0)
|
|
125
126
|
content: () => getTitle(), // String, function, or array
|
|
126
127
|
},
|
|
127
128
|
|
|
@@ -148,7 +149,7 @@ type RuleContext = {
|
|
|
148
149
|
}
|
|
149
150
|
```
|
|
150
151
|
|
|
151
|
-
Frontmatter is automatically extracted
|
|
152
|
+
Frontmatter is automatically extracted if available. If the document has no frontmatter block, `context.frontmatter` remains `undefined`.
|
|
152
153
|
|
|
153
154
|
```ts
|
|
154
155
|
const rules: Rules = {
|
|
@@ -181,11 +182,11 @@ Single primitive value:
|
|
|
181
182
|
<!-- repeat(3) -->
|
|
182
183
|
```
|
|
183
184
|
|
|
184
|
-
|
|
185
|
+
Prefer object arguments over single primitive values for all but the most contextually clear argument values.
|
|
185
186
|
|
|
186
|
-
|
|
187
|
+
Any JSON5 value is supported: objects, arrays, strings, numbers, and booleans. Comments without parentheses receive an empty object `{}` as their options.
|
|
187
188
|
|
|
188
|
-
|
|
189
|
+
For simplicity's sake, only a single argument position is supported. If you need pass multiple arguments, wrap them in an object. For security's sake, only JSON5 / JSON values are permitted in keyword arguments, no JavaScript is evaluated.
|
|
189
190
|
|
|
190
191
|
### Examples
|
|
191
192
|
|
|
@@ -221,20 +222,20 @@ import remarkMdat from 'remark-mdat'
|
|
|
221
222
|
|
|
222
223
|
// Create the rules
|
|
223
224
|
const rules: Rules = {
|
|
224
|
-
time:
|
|
225
|
+
time: new Date().toDateString(),
|
|
225
226
|
}
|
|
226
227
|
|
|
227
228
|
const markdownInput = '<!-- time -->'
|
|
228
229
|
|
|
229
230
|
// Pass the rules to remarkMdat
|
|
230
|
-
const markdownOutput = await remark().use(remarkMdat, rules).process(markdownInput)
|
|
231
|
+
const markdownOutput = await remark().use(remarkMdat, { rules }).process(markdownInput)
|
|
231
232
|
|
|
232
233
|
console.log(markdownOutput.toString())
|
|
233
234
|
|
|
234
235
|
// Logs:
|
|
235
236
|
// <!-- time -->
|
|
236
237
|
//
|
|
237
|
-
// Mon
|
|
238
|
+
// Mon April 01 2026
|
|
238
239
|
//
|
|
239
240
|
// <!-- /time -->
|
|
240
241
|
```
|
|
@@ -274,10 +275,122 @@ Errors and warnings are reported inline during expansion via [VFile messages](ht
|
|
|
274
275
|
|
|
275
276
|
_Exported as `mdatExpand(tree: Root, file: VFile, rules: Rules): Promise<void>`_
|
|
276
277
|
|
|
278
|
+
## Migrating from remark-mdat 1.x to 2.x
|
|
279
|
+
|
|
280
|
+
Version 2.0 simplifies and solidifies the API by removing several configuration options and validation features that added complexity without sufficient benefit. The core expansion behavior is unchanged — the plugin still matches HTML comments to rules and expands them — but the way you configure it has changed.
|
|
281
|
+
|
|
282
|
+
### Simplified options
|
|
283
|
+
|
|
284
|
+
In 1.x, the plugin accepted an options object with multiple fields to customize parsing and generation:
|
|
285
|
+
|
|
286
|
+
```ts
|
|
287
|
+
// 1.x
|
|
288
|
+
remark().use(remarkMdat, {
|
|
289
|
+
rules: { title: () => '# My Title' },
|
|
290
|
+
addMetaComment: true,
|
|
291
|
+
closingPrefix: '/',
|
|
292
|
+
keywordPrefix: 'mm-',
|
|
293
|
+
metaCommentIdentifier: '+',
|
|
294
|
+
})
|
|
295
|
+
```
|
|
296
|
+
|
|
297
|
+
In 2.x, the configuration options for parsing and generation have been removed. The `Options` object now contains only a `rules` field:
|
|
298
|
+
|
|
299
|
+
```ts
|
|
300
|
+
// 2.x
|
|
301
|
+
remark().use(remarkMdat, {
|
|
302
|
+
rules: { title: () => '# My Title' },
|
|
303
|
+
})
|
|
304
|
+
```
|
|
305
|
+
|
|
306
|
+
If you were importing `MdatOptions`, `MdatExpandOptions`, `MdatCheckOptions`, or `MdatCleanOptions`, replace them with `Options` (for plugin configuration) or `Rules` (for the rules record).
|
|
307
|
+
|
|
308
|
+
### Removed options
|
|
309
|
+
|
|
310
|
+
The following plugin options have been removed entirely:
|
|
311
|
+
|
|
312
|
+
| Removed option | Migration |
|
|
313
|
+
| ----------------------- | ------------------------------------------------------------------------ |
|
|
314
|
+
| `addMetaComment` | Remove. Auto-generated warning comments are no longer supported. |
|
|
315
|
+
| `metaCommentIdentifier` | Remove. The `<!--+ ... +-->` meta comment syntax is gone. |
|
|
316
|
+
| `closingPrefix` | Remove. The closing prefix is now always `/` (e.g. `<!-- /keyword -->`). |
|
|
317
|
+
| `keywordPrefix` | Remove. Keyword prefixing / namespacing is no longer supported. |
|
|
318
|
+
|
|
319
|
+
### Removed rule properties
|
|
320
|
+
|
|
321
|
+
| Removed property | Migration |
|
|
322
|
+
| ---------------- | ------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
323
|
+
| `required` | Remove. All rules are treated equally. Missing comments produce a warning instead of an error. |
|
|
324
|
+
| `order | Remove. The 1.x `order` property enforced comment _position_ in the document. In 2.x, `order` controls _processing priority_ only (default: `0`). |
|
|
325
|
+
|
|
326
|
+
### Changed rule properties
|
|
327
|
+
|
|
328
|
+
| Changed property | Migration |
|
|
329
|
+
| ------------------ | ------------------ |
|
|
330
|
+
| `applicationOrder` | Change to `order`. |
|
|
331
|
+
|
|
332
|
+
### Removed validation utility
|
|
333
|
+
|
|
334
|
+
The `mdast-util-mdat-check` utility and its export `mdatCheck` have been removed. Validation logic (missing rules, empty content, rule errors) is now handled inline during expansion by `mdatExpand`, which reports issues as VFile messages. Use `reporterMdat` to format and display these messages.
|
|
335
|
+
|
|
336
|
+
### Rule function signature change
|
|
337
|
+
|
|
338
|
+
In 1.x, rule content functions received the mdast tree directly as the second argument:
|
|
339
|
+
|
|
340
|
+
```ts
|
|
341
|
+
// 1.x
|
|
342
|
+
const rules = {
|
|
343
|
+
toc: (_options, tree) => generateTocFromTree(tree),
|
|
344
|
+
}
|
|
345
|
+
```
|
|
346
|
+
|
|
347
|
+
In 2.x, the second argument is a `RuleContext` object containing the tree, parsed frontmatter, and file path:
|
|
348
|
+
|
|
349
|
+
```ts
|
|
350
|
+
// 2.x
|
|
351
|
+
const rules = {
|
|
352
|
+
toc: (_options, context) => generateTocFromTree(context.tree),
|
|
353
|
+
}
|
|
354
|
+
```
|
|
355
|
+
|
|
356
|
+
### Stricter argument syntax
|
|
357
|
+
|
|
358
|
+
In 1.x, the argument parser was very permissive — parentheses were optional, bare key-value pairs were auto-wrapped in braces, and space-separated arguments worked:
|
|
359
|
+
|
|
360
|
+
```md
|
|
361
|
+
<!-- greeting name: "Alice" -->
|
|
362
|
+
<!-- greeting {name: "Alice"} -->
|
|
363
|
+
<!-- greeting({name: "Alice"}) -->
|
|
364
|
+
```
|
|
365
|
+
|
|
366
|
+
In 2.x, arguments **must** use function-call syntax with parentheses. The content inside the parentheses is parsed as [JSON5](https://json5.org/):
|
|
367
|
+
|
|
368
|
+
```md
|
|
369
|
+
<!-- greeting({name: 'Alice'}) -->
|
|
370
|
+
```
|
|
371
|
+
|
|
372
|
+
Bare or space-separated arguments like `<!-- greeting name: "Alice" -->` will no longer be parsed — the extra text after the keyword is ignored and the rule receives an empty `{}` options object.
|
|
373
|
+
|
|
374
|
+
As a trade-off for the stricter syntax, primitive values are now supported as arguments: `<!-- repeat(3) -->`, `<!-- show("hello") -->`.
|
|
375
|
+
|
|
376
|
+
### Comment-style comments are ignored
|
|
377
|
+
|
|
378
|
+
HTML comments using code-style prefixes (`<!-- // ... -->`, `<!-- # ... -->`, `<!-- /* ... */ -->`) are now ignored by the parser, so you can use them for regular comments alongside mdat keywords without triggering warnings. This replaces 1.x parser configuration options like `keywordPrefix`.
|
|
379
|
+
|
|
380
|
+
### Compound rule error handling
|
|
381
|
+
|
|
382
|
+
In 1.x, a failing sub-rule in a compound rule (array of rules) caused the entire expansion to fail. In 2.x, individual sub-rule failures are reported as warnings and skipped — the expansion only fails if every sub-rule fails.
|
|
383
|
+
|
|
384
|
+
### Removed export: `deepMergeDefined`
|
|
385
|
+
|
|
386
|
+
The `deepMergeDefined` utility has been moved to the [`mdat`](https://github.com/kitschpatrol/mdat) package. If you were importing it from `remark-mdat`, import it from `mdat` instead.
|
|
387
|
+
|
|
277
388
|
## Implementation notes
|
|
278
389
|
|
|
279
390
|
This project was split from a monorepo containing both `mdat` and `remark-mdat` into separate repos in July 2024.
|
|
280
391
|
|
|
392
|
+
The API was redesigned and simplified for version 2 in March 2026.
|
|
393
|
+
|
|
281
394
|
Remark is not a peer dependency on account of this discussion: [strip-markdown/issues/24](https://github.com/remarkjs/strip-markdown/issues/24)
|
|
282
395
|
|
|
283
396
|
## Maintainers
|