remark-mdat 2.0.0-preview.1 → 2.0.0-preview.2
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 +14 -6
- package/dist/index.js +18 -12
- package/package.json +4 -3
- package/readme.md +32 -2
package/dist/index.d.ts
CHANGED
|
@@ -7,6 +7,14 @@ import { Plugin } from "unified";
|
|
|
7
7
|
|
|
8
8
|
//#region src/lib/mdat/rules.d.ts
|
|
9
9
|
type SimplifyDeep<T> = Simplify<MergeDeep<T, T>>;
|
|
10
|
+
/**
|
|
11
|
+
* Context passed to rule content functions during expansion.
|
|
12
|
+
*/
|
|
13
|
+
type RuleContext = {
|
|
14
|
+
/** File path of the source document, if known. */filePath: string | undefined; /** Parsed YAML frontmatter from the document, if present. */
|
|
15
|
+
frontmatter: Record<string, unknown> | undefined; /** The full mdast AST of the document. Do not mutate. */
|
|
16
|
+
tree: Root;
|
|
17
|
+
};
|
|
10
18
|
/**
|
|
11
19
|
* Strict normalized rules used internally.
|
|
12
20
|
* Rules normalized to a form with async content functions and other default metadata
|
|
@@ -17,7 +25,7 @@ type NormalizedRule = {
|
|
|
17
25
|
* The function that generates the expanded Markdown string.
|
|
18
26
|
* For 'compound' rules, this can be an array of rules (without keywords).
|
|
19
27
|
*/
|
|
20
|
-
content: ((options: JsonValue,
|
|
28
|
+
content: ((options: JsonValue, context: RuleContext) => Promise<string>) | NormalizedRule[];
|
|
21
29
|
/**
|
|
22
30
|
* The order in which the rule should be applied during processing
|
|
23
31
|
* Helpful if a rule depends on the presence of content generated by another rule
|
|
@@ -29,7 +37,7 @@ type Rule =
|
|
|
29
37
|
/**
|
|
30
38
|
* Function that returns the Markdown string to expand at the comment site.
|
|
31
39
|
*/
|
|
32
|
-
((options: JsonValue,
|
|
40
|
+
((options: JsonValue, context: RuleContext) => Promise<string> | string)
|
|
33
41
|
/**
|
|
34
42
|
* Compound rules may be defined an array of rules, without keywords.
|
|
35
43
|
* Can be defined at the top level, if no validation metadata is required, or as the 'content' value
|
|
@@ -54,11 +62,11 @@ type Rule =
|
|
|
54
62
|
* `<!-- keyword({something: true}) -->` or
|
|
55
63
|
* `<!-- keyword {something: true}-->`
|
|
56
64
|
* Sets options to {something: true}
|
|
57
|
-
* @param
|
|
58
|
-
*
|
|
65
|
+
* @param context
|
|
66
|
+
* Rule context containing the mdast AST, parsed frontmatter, and file path.
|
|
59
67
|
* @returns A string with the generated content. The string will be parsed as Markdown and inserted into the document at the comment's location.
|
|
60
68
|
*/
|
|
61
|
-
content: ((options: JsonValue,
|
|
69
|
+
content: ((options: JsonValue, context: RuleContext) => Promise<string> | string) | Rule[] | string;
|
|
62
70
|
/**
|
|
63
71
|
* The order in which the rule should be applied during processing.
|
|
64
72
|
* Defaults to 0.
|
|
@@ -165,4 +173,4 @@ type Options = Rules;
|
|
|
165
173
|
*/
|
|
166
174
|
declare const remarkMdat: Plugin<[Options], Root>;
|
|
167
175
|
//#endregion
|
|
168
|
-
export { type MdatFileReport, type MdatMessage, type NormalizedRule, type NormalizedRules, type Options, type Rule, type Rules, type SimplifyDeep, remarkMdat as default, getMdatReports, getSoleRule, getSoleRuleKey, mdat, mdatClean, mdatExpand, mdatSplit, rulesSchema as optionsSchema, rulesSchema, reporterMdat, setLogger };
|
|
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, rulesSchema as optionsSchema, rulesSchema, reporterMdat, setLogger };
|
package/dist/index.js
CHANGED
|
@@ -4,6 +4,7 @@ import picocolors from "picocolors";
|
|
|
4
4
|
import { createLogger, injectionHelper } from "lognow";
|
|
5
5
|
import json5 from "json5";
|
|
6
6
|
import { VFileMessage } from "vfile-message";
|
|
7
|
+
import { matter } from "gray-matter-es";
|
|
7
8
|
import { remark } from "remark";
|
|
8
9
|
import remarkGfm from "remark-gfm";
|
|
9
10
|
import { z } from "zod";
|
|
@@ -212,7 +213,7 @@ function normalizeRules(rules) {
|
|
|
212
213
|
order: 0
|
|
213
214
|
};
|
|
214
215
|
else if (typeof rule === "function") normalizedRules[keyword] = {
|
|
215
|
-
content: async (options,
|
|
216
|
+
content: async (options, context) => rule(options, context),
|
|
216
217
|
order: 0
|
|
217
218
|
};
|
|
218
219
|
else if (Array.isArray(rule)) normalizedRules[keyword] = {
|
|
@@ -232,7 +233,7 @@ function normalizeRules(rules) {
|
|
|
232
233
|
else {
|
|
233
234
|
const ruleContent = rule.content;
|
|
234
235
|
normalizedRules[keyword] = {
|
|
235
|
-
content: async (options,
|
|
236
|
+
content: async (options, context) => ruleContent(options, context),
|
|
236
237
|
order: rule.order ?? 0
|
|
237
238
|
};
|
|
238
239
|
}
|
|
@@ -275,25 +276,20 @@ const keywordSchema = z.string().check(z.refine((key) => !/^[/*#]/.test(key), {
|
|
|
275
276
|
const rulesSchema = z.record(keywordSchema, ruleSchema).describe("MDAT Rules");
|
|
276
277
|
const normalizedRulesSchema = z.record(keywordSchema, normalizedRuleSchema).describe("MDAT Rules");
|
|
277
278
|
/**
|
|
278
|
-
* Compound rule helpers
|
|
279
|
+
* Compound rule helpers for expanding rule content.
|
|
279
280
|
*/
|
|
280
|
-
async function getRuleContent(rule, options,
|
|
281
|
+
async function getRuleContent(rule, options, context) {
|
|
281
282
|
if (Array.isArray(rule.content)) {
|
|
282
283
|
const subruleContent = [];
|
|
283
284
|
for (const [index, subrule] of rule.content.entries()) {
|
|
284
285
|
const subruleOptions = Array.isArray(options) ? options.at(index) : void 0;
|
|
285
|
-
|
|
286
|
-
subruleContent.push(await getRuleContent(subrule, subruleOptions ?? {}, tree));
|
|
287
|
-
} catch (error) {
|
|
288
|
-
if (check) throw error;
|
|
289
|
-
}
|
|
286
|
+
subruleContent.push(await getRuleContent(subrule, subruleOptions ?? {}, context));
|
|
290
287
|
}
|
|
291
288
|
return subruleContent.join("\n\n");
|
|
292
289
|
}
|
|
293
290
|
try {
|
|
294
|
-
return await rule.content(options,
|
|
291
|
+
return await rule.content(options, context);
|
|
295
292
|
} catch (error) {
|
|
296
|
-
if (check) throw error;
|
|
297
293
|
throw new Error("Failed to expand content", { cause: error });
|
|
298
294
|
}
|
|
299
295
|
}
|
|
@@ -340,6 +336,16 @@ function getSoleRecord(record) {
|
|
|
340
336
|
async function mdatExpand(tree, file, rules) {
|
|
341
337
|
validateRules(rules);
|
|
342
338
|
const normalizedRules = normalizeRules(rules);
|
|
339
|
+
const frontmatter = (() => {
|
|
340
|
+
if (typeof file.value !== "string") return;
|
|
341
|
+
const { data } = matter(file.value);
|
|
342
|
+
return Object.keys(data).length > 0 ? data : void 0;
|
|
343
|
+
})();
|
|
344
|
+
const context = {
|
|
345
|
+
filePath: file.history.length > 0 ? file.path : void 0,
|
|
346
|
+
frontmatter,
|
|
347
|
+
tree
|
|
348
|
+
};
|
|
343
349
|
const commentMarkers = [];
|
|
344
350
|
visit(tree, "html", (node, index, parent) => {
|
|
345
351
|
if (parent === void 0 || index === void 0) return CONTINUE;
|
|
@@ -357,7 +363,7 @@ async function mdatExpand(tree, file, rules) {
|
|
|
357
363
|
const rule = normalizedRules[keyword];
|
|
358
364
|
let newMarkdownString = "";
|
|
359
365
|
try {
|
|
360
|
-
newMarkdownString = await getRuleContent(rule, options,
|
|
366
|
+
newMarkdownString = await getRuleContent(rule, options, context);
|
|
361
367
|
if (newMarkdownString.trim() === "") saveLog(file, "error", "expand", `Got empty content when expanding ${html}`, node);
|
|
362
368
|
} catch (error) {
|
|
363
369
|
if (error instanceof Error) {
|
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.2",
|
|
4
4
|
"description": "A remark plugin implementing the Markdown Autophagic Template (MDAT) system.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"mdat",
|
|
@@ -43,6 +43,7 @@
|
|
|
43
43
|
"dependencies": {
|
|
44
44
|
"@types/mdast": "^4.0.4",
|
|
45
45
|
"@types/unist": "^3.0.3",
|
|
46
|
+
"gray-matter-es": "^0.2.1",
|
|
46
47
|
"hast-util-from-html": "^2.0.3",
|
|
47
48
|
"json5": "^2.2.3",
|
|
48
49
|
"lognow": "^0.5.2",
|
|
@@ -67,7 +68,7 @@
|
|
|
67
68
|
"vitest": "^4.1.1"
|
|
68
69
|
},
|
|
69
70
|
"engines": {
|
|
70
|
-
"node": ">=20.19.
|
|
71
|
+
"node": ">=20.19.6"
|
|
71
72
|
},
|
|
72
73
|
"devEngines": {
|
|
73
74
|
"runtime": {
|
|
@@ -82,7 +83,7 @@
|
|
|
82
83
|
"fix": "ksc fix",
|
|
83
84
|
"lint": "ksc lint",
|
|
84
85
|
"release": "bumpp --commit 'Release: %s' && pnpm run build && NPM_AUTH_TOKEN=$(op read 'op://Personal/npm/token') && pnpm publish",
|
|
85
|
-
"release-preview": "bumpp --preid preview --commit 'Release: %s' && NPM_AUTH_TOKEN=$(op read 'op://Personal/npm/token') && pnpm publish --tag preview",
|
|
86
|
+
"release-preview": "bumpp --preid preview --commit 'Release: %s' && pnpm run build && NPM_AUTH_TOKEN=$(op read 'op://Personal/npm/token') && pnpm publish --tag preview",
|
|
86
87
|
"test": "vitest run"
|
|
87
88
|
}
|
|
88
89
|
}
|
package/readme.md
CHANGED
|
@@ -128,8 +128,38 @@ const rules: Rules = {
|
|
|
128
128
|
// Array: compound rule combining multiple sub-rules
|
|
129
129
|
header: ['# My Project', () => getDescription()],
|
|
130
130
|
|
|
131
|
-
// Function with
|
|
132
|
-
toc: (_options,
|
|
131
|
+
// Function with context: access the document tree, frontmatter, and file path
|
|
132
|
+
toc: (_options, context) => generateTocFromTree(context.tree),
|
|
133
|
+
}
|
|
134
|
+
```
|
|
135
|
+
|
|
136
|
+
#### Rule context
|
|
137
|
+
|
|
138
|
+
Rule content functions receive a `RuleContext` object as their second argument, providing access to the document being processed:
|
|
139
|
+
|
|
140
|
+
```ts
|
|
141
|
+
type RuleContext = {
|
|
142
|
+
/** File path of the source document, if known. */
|
|
143
|
+
filePath: string | undefined
|
|
144
|
+
/** Parsed YAML frontmatter from the document, if present. */
|
|
145
|
+
frontmatter: Record<string, unknown> | undefined
|
|
146
|
+
/** The full mdast AST of the document. Do not mutate. */
|
|
147
|
+
tree: Root
|
|
148
|
+
}
|
|
149
|
+
```
|
|
150
|
+
|
|
151
|
+
Frontmatter is automatically extracted from the raw Markdown source using [gray-matter-es](https://github.com/ryoppippi/gray-matter-es), so it works regardless of whether `remark-frontmatter` is in your pipeline. If the document has no frontmatter block, `context.frontmatter` is `undefined`.
|
|
152
|
+
|
|
153
|
+
```ts
|
|
154
|
+
const rules: Rules = {
|
|
155
|
+
// Access frontmatter values
|
|
156
|
+
title: (_options, context) => `# ${context.frontmatter?.title ?? 'Untitled'}`,
|
|
157
|
+
|
|
158
|
+
// Use the file path
|
|
159
|
+
source: (_options, context) => `Source: ${context.filePath ?? 'unknown'}`,
|
|
160
|
+
|
|
161
|
+
// Traverse the AST
|
|
162
|
+
toc: (_options, context) => generateTocFromTree(context.tree),
|
|
133
163
|
}
|
|
134
164
|
```
|
|
135
165
|
|