remark-mdat 1.2.2 → 1.2.3

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "remark-mdat",
3
- "version": "1.2.2",
3
+ "version": "1.2.3",
4
4
  "description": "A remark plugin implementing the Markdown Autophagic Template (MDAT) system.",
5
5
  "keywords": [
6
6
  "mdat",
@@ -27,6 +27,12 @@
27
27
  "url": "https://ericmika.com"
28
28
  },
29
29
  "type": "module",
30
+ "exports": {
31
+ ".": {
32
+ "types": "./dist/index.d.ts",
33
+ "default": "./dist/index.js"
34
+ }
35
+ },
30
36
  "main": "./dist/index.js",
31
37
  "module": "./dist/index.js",
32
38
  "types": "./dist/index.d.ts",
@@ -35,34 +41,42 @@
35
41
  ],
36
42
  "dependencies": {
37
43
  "@types/mdast": "^4.0.4",
38
- "@types/node": "^20.19.30",
39
44
  "@types/unist": "^3.0.3",
40
- "picocolors": "^1.1.1",
41
- "type-fest": "^5.4.1",
42
- "unified": "^11.0.5",
43
- "vfile": "^6.0.3",
44
- "zod": "^3.25.76"
45
- },
46
- "devDependencies": {
47
- "@kitschpatrol/shared-config": "^5.12.0",
48
- "bumpp": "^10.4.0",
49
45
  "cli-table3": "^0.6.5",
50
46
  "deepmerge-ts": "^7.1.5",
51
47
  "hast-util-from-html": "^2.0.3",
52
48
  "json5": "^2.2.3",
49
+ "picocolors": "^1.1.1",
53
50
  "remark": "^15.0.1",
54
51
  "remark-gfm": "^4.0.1",
55
- "tsdown": "^0.19.0",
56
- "typescript": "~5.9.3",
57
- "unist-util-visit": "^5.0.0",
52
+ "type-fest": "^5.4.4",
53
+ "unified": "^11.0.5",
54
+ "unist-util-visit": "^5.1.0",
55
+ "vfile": "^6.0.3",
58
56
  "vfile-message": "^4.0.3",
59
- "vitest": "^4.0.17"
57
+ "zod": "^3.25.76"
58
+ },
59
+ "devDependencies": {
60
+ "@arethetypeswrong/core": "^0.18.2",
61
+ "@kitschpatrol/shared-config": "^6.0.0",
62
+ "@types/node": "~20.19.33",
63
+ "bumpp": "^10.4.1",
64
+ "publint": "^0.3.17",
65
+ "tsdown": "^0.20.3",
66
+ "typescript": "~5.9.3",
67
+ "vitest": "^4.0.18"
60
68
  },
61
69
  "engines": {
62
- "node": ">=20.19.0"
70
+ "node": ">=20.0.0"
71
+ },
72
+ "devEngines": {
73
+ "runtime": {
74
+ "name": "node",
75
+ "version": ">=22.21.0"
76
+ }
63
77
  },
64
78
  "scripts": {
65
- "build": "tsdown --no-fixed-extension --dts false && tsc -p tsconfig.build.json",
79
+ "build": "tsdown",
66
80
  "clean": "git rm -f pnpm-lock.yaml ; git clean -fdX",
67
81
  "dev": "pnpm run test",
68
82
  "fix": "ksc fix",
package/readme.md CHANGED
@@ -97,15 +97,42 @@ remark().use(remarkMdat)
97
97
 
98
98
  #### Options
99
99
 
100
- The plugin accepts an optional options object which exposes some configuration options and, most importantly, determines how comments in the source Markdown file will be expanded via the `rules` field:
100
+ The plugin accepts an optional options object. All fields are optional:
101
+
102
+ | Option | Type | Default | Description |
103
+ | ----------------------- | ------------------- | ------- | ----------------------------------------------------------------------------------------------------------------------------------------------------- |
104
+ | `rules` | `Rules` | `{}` | A record mapping comment keywords to rules that determine what content is expanded at each comment site. See [Rules](#rules) below. |
105
+ | `addMetaComment` | `boolean \| string` | `false` | If `true`, prepends a warning comment to the document noting that content was auto-generated. If a `string`, uses that string as the warning message. |
106
+ | `closingPrefix` | `string` | `'/'` | The prefix used to identify closing comment tags, e.g. the `/` in `<!-- /keyword -->`. |
107
+ | `keywordPrefix` | `string` | `''` | A prefix required on all mdat comments. Useful for namespacing, e.g. setting `'mm-'` means only `<!-- mm-keyword -->` comments are processed. |
108
+ | `metaCommentIdentifier` | `string` | `'+'` | The character used to identify auto-generated meta comments, e.g. `<!--+ ... +-->`. |
109
+
110
+ #### Rules
111
+
112
+ Rules are defined as a `Record<string, Rule>` where each key is a keyword matching an HTML comment in the Markdown file (e.g. `title` matches `<!-- title -->`).
113
+
114
+ A `Rule` value can take several forms:
101
115
 
102
116
  ```ts
103
- export type Options = {
104
- addMetaComment?: boolean | string // Default: false
105
- closingPrefix?: string // Default: '/',
106
- keywordPrefix?: string // Default: '',
107
- metaCommentIdentifier?: string // Default: '+',
108
- rules?: Rules // Default: a single test rule for the 'mdat' keyword
117
+ const rules: Rules = {
118
+ // String: direct replacement
119
+ greeting: 'Hello, world!',
120
+ // Array: compound rule combining multiple sub-rules
121
+ header: ['# My Project', () => getDescription()],
122
+ // Function with arguments: receives parsed options from the comment
123
+ // e.g. <!-- greeting({name: "Alice"}) --> or <!-- greeting {name: "Alice"} -->
124
+ personalGreeting: (options) => `Hello, ${options.name}!`,
125
+ // Function: dynamic content (sync or async)
126
+ time: () => new Date().toDateString(),
127
+ // Object: rule with validation metadata
128
+ title: {
129
+ applicationOrder: 0, // Processing priority (default: 0)
130
+ content: () => getTitle(), // String, function, or array
131
+ order: 1, // Expected position relative to other comments
132
+ required: true, // Error if comment is missing (default: false)
133
+ },
134
+ // Function with document access: receives the full mdast tree
135
+ toc: (_options, tree) => generateTocFromTree(tree),
109
136
  }
110
137
  ```
111
138
 
@@ -173,35 +200,42 @@ The remark-mdat plugin chains these utilities together to accommodate the typica
173
200
 
174
201
  Composite transformer function performing end-to-end mdat comment expansion and validation on Markdown ASTs by chaining the other utility functions described below.
175
202
 
176
- _Exported as `mdat`_
203
+ _Exported as `mdat(tree: Root, file: VFile, options: MdatOptions): Promise<void>`_
177
204
 
178
- Utilities wrapped by `mdast-util-mdat`:
205
+ `MdatOptions` includes `addMetaComment`, `closingPrefix`, `keywordPrefix`, `metaCommentIdentifier`, and `rules` (all required, unlike the plugin's `Options` where they are optional with defaults).
179
206
 
207
+ Utilities wrapped by `mdast-util-mdat`:
180
208
  - [**`mdast-util-mdat-split`**](./src/lib/mdast-utils/mdast-util-mdat-split.ts)
181
209
 
182
- Transformer function that allows inline mdat expansion comments.
210
+ Transformer function that splits multi-comment HTML nodes into individual mdast nodes, allowing inline mdat expansion comments.
183
211
 
184
- _Exported as `mdatSplit`_
212
+ _Exported as `mdatSplit(tree: Root, file: VFile): void`_
185
213
 
186
214
  - [**`mdast-util-mdat-clean`**](./src/lib/mdast-utils/mdast-util-mdat-clean.ts)
187
215
 
188
216
  Transformer function that "resets" all mdat comment expansions in a file, collapsing expanded comments back into single-line placeholders.
189
217
 
190
- _Exported as `mdatClean`_
218
+ _Exported as `mdatClean(tree: Root, file: VFile, options: MdatCleanOptions): void`_
219
+
220
+ `MdatCleanOptions` includes `closingPrefix`, `keywordPrefix`, and `metaCommentIdentifier`.
191
221
 
192
222
  - [**`mdast-util-mdat-expand`**](./src/lib/mdast-utils/mdast-util-mdat-expand.ts)
193
223
 
194
- Transformer function that expands mdat comments (e.g. `<!-- title -->`) in a Markdown file according to the rule set passed in to the `MdatExpandOptions` argument.
224
+ Transformer function that expands mdat comments (e.g. `<!-- title -->`) in a Markdown file according to the rule set passed in to the options argument.
195
225
 
196
- _Exported as `mdatExpand`_
226
+ _Exported as `mdatExpand(tree: Root, file: VFile, options: MdatExpandOptions): Promise<void>`_
227
+
228
+ `MdatExpandOptions` includes `addMetaComment`, `closingPrefix`, `keywordPrefix`, `metaCommentIdentifier`, and `rules`.
197
229
 
198
230
  - [**`mdast-util-mdat-check`**](./src/lib/mdast-utils/mdast-util-mdat-check.ts)
199
231
 
200
- Transformer function that validates an expanded Markdown document against the requirements defined in the rules passed in to the `MdatCheckOptions` argument.
232
+ Transformer function that validates an expanded Markdown document against the requirements defined in the rules passed in to the options argument. Does not modify the tree, it only appends messages to the VFile.
233
+
234
+ _Exported as `mdatCheck(tree: Root, file: VFile, options: MdatCheckOptions): Promise<void>`_
201
235
 
202
- See `reporterMdat` to extract, format, and log results from VFile messages written by `mdatCheck`. This function does not modify the tree, it only appends messages to the VFiles passed through it.
236
+ `MdatCheckOptions` extends `MdatExpandOptions` with a `paranoid` boolean for extra validation checks.
203
237
 
204
- _Exported as `mdatCheck`_
238
+ See `reporterMdat` to extract, format, and log results from VFile messages written by `mdatCheck`.
205
239
 
206
240
  ## Implementation notes
207
241
 
@@ -1,16 +0,0 @@
1
- import type { Root } from 'mdast';
2
- import type { VFile } from 'vfile';
3
- import type { Rules } from '../mdat/rules';
4
- export type Options = {
5
- addMetaComment: boolean | string;
6
- closingPrefix: string;
7
- keywordPrefix: string;
8
- metaCommentIdentifier: string;
9
- /** Enable extra checks, too noisy for real life. */
10
- paranoid: boolean;
11
- rules: Rules;
12
- };
13
- /**
14
- * Mdast utility function to check mdat source document, and output.
15
- */
16
- export declare function mdatCheck(tree: Root, file: VFile, options: Options): Promise<void>;
@@ -1,13 +0,0 @@
1
- import type { Root } from 'mdast';
2
- import type { VFile } from 'vfile';
3
- export type Options = {
4
- closingPrefix: string;
5
- keywordPrefix: string;
6
- metaCommentIdentifier: string;
7
- };
8
- /**
9
- * Collapses any expanded mdat comments and removes meta comments,
10
- * effectively resetting the document to its pre-expansion state. No-op if no
11
- * mdat comments are found.
12
- */
13
- export declare function mdatClean(tree: Root, file: VFile, options: Options): void;
@@ -1,11 +0,0 @@
1
- import type { Root } from 'mdast';
2
- import type { VFile } from 'vfile';
3
- import type { Rules } from '../mdat/rules';
4
- export type Options = {
5
- addMetaComment: boolean | string;
6
- closingPrefix: string;
7
- keywordPrefix: string;
8
- metaCommentIdentifier: string;
9
- rules: Rules;
10
- };
11
- export declare function mdatExpand(tree: Root, file: VFile, options: Options): Promise<void>;
@@ -1,8 +0,0 @@
1
- import type { Html, Root, Text } from 'mdast';
2
- import type { VFile } from 'vfile';
3
- /**
4
- * Mdast utility plugin to split any multi-comment nodes and their content into individual MDAST HTML
5
- * nodes. They're wrapped in a paragraph so as not to introduce new breaks.
6
- */
7
- export declare function mdatSplit(tree: Root, file: VFile): void;
8
- export declare function splitHtmlIntoMdastNodes(mdastNode: Html): Array<Html | Text>;
@@ -1,11 +0,0 @@
1
- import type { Root } from 'mdast';
2
- import type { VFile } from 'vfile';
3
- import type { Rules } from '../mdat/rules';
4
- export type Options = {
5
- addMetaComment: boolean | string;
6
- closingPrefix: string;
7
- keywordPrefix: string;
8
- metaCommentIdentifier: string;
9
- rules: Rules;
10
- };
11
- export declare function mdat(tree: Root, file: VFile, options: Options): Promise<void>;
@@ -1 +0,0 @@
1
- export declare function deepMergeDefined<T extends Record<string, unknown>>(...objects: T[]): T;
@@ -1,12 +0,0 @@
1
- declare const log: {
2
- verbose: boolean;
3
- log(...data: unknown[]): void;
4
- logPrefixed(prefix: string, ...data: unknown[]): void;
5
- info(...data: unknown[]): void;
6
- infoPrefixed(prefix: string, ...data: unknown[]): void;
7
- warn(...data: unknown[]): void;
8
- warnPrefixed(prefix: string, ...data: unknown[]): void;
9
- error(...data: unknown[]): void;
10
- errorPrefixed(prefix: string, ...data: unknown[]): void;
11
- };
12
- export default log;
@@ -1,23 +0,0 @@
1
- import type { Node } from 'unist';
2
- import type { VFile } from 'vfile';
3
- /**
4
- * Tries to provide a simpler wrapper to vfile.message
5
- */
6
- export type MdatMessage = {
7
- column?: number;
8
- level: 'error' | 'info' | 'warn';
9
- line?: number;
10
- message: string;
11
- source?: string;
12
- };
13
- export type MdatFileReport = {
14
- destinationPath?: string;
15
- errors: MdatMessage[];
16
- infos: MdatMessage[];
17
- sourcePath: string;
18
- warnings: MdatMessage[];
19
- };
20
- export declare function saveLog(file: VFile, level: 'error' | 'info' | 'warn', source: string, message: string, line?: number, column?: number): void;
21
- export declare function saveLog(file: VFile, level: 'error' | 'info' | 'warn', source: string, message: string, node?: Node): void;
22
- export declare function getMdatReports(files: VFile[]): MdatFileReport[];
23
- export declare function reporterMdat(files: VFile[]): void;
@@ -1,62 +0,0 @@
1
- import type { Html, Parent } from 'mdast';
2
- import type { JsonValue, Simplify } from 'type-fest';
3
- /**
4
- * Structured data about a parsed comment.
5
- * Note that this is a discriminated union based on the `type` field.
6
- */
7
- type CommentMarker = Simplify<{
8
- /** The complete original comment, e.g. `<!-- keyword -->` */
9
- html: string;
10
- } & ({
11
- /** Character used to delimit closing tags, e.g. the `/` in `<!-- /keyword -->` */
12
- closingPrefix: string;
13
- /** The first complete word in the comment */
14
- keyword: string;
15
- /** The unique keyword prefix */
16
- keywordPrefix: string;
17
- /** Parsed JSON object of argument string that followed the keyword, empty object if nothing passed */
18
- options: JsonValue;
19
- /**
20
- * `open`: A mdat-style opening comment tag, e.g. `<!-- keyword -->` \
21
- * `close`: A mdat-style closing comment tag, e.g. `<!-- /keyword -->`
22
- */
23
- type: 'close' | 'open';
24
- } | {
25
- /** The original text inside the comment, e.g. `<!-- content -->` */
26
- content: string;
27
- /**
28
- * `meta`: A mdat-style generated meta comment tag \
29
- * `native`: A normal comment that does not match the the `keywordPrefix` (if specified)
30
- */
31
- type: 'meta' | 'native';
32
- })>;
33
- /**
34
- * Parsed comment with additional information about the Mdast Node and its Parent.
35
- */
36
- export type CommentMarkerNode = Simplify<CommentMarker & {
37
- /** Original Mdast HTML Node where the comment was found. */
38
- node: Html;
39
- /** Parent of original Mdast HTML Node where the comment was found. */
40
- parent: Parent;
41
- }>;
42
- type CommentMarkerParseOptions = {
43
- /** Character to identify closing tags, e.g. the `/` in `<!-- /keyword -->` */
44
- closingPrefix: string;
45
- /** Prefix to require on all mdat comments, e.g. `mm-` */
46
- keywordPrefix: string;
47
- /** Means of identifying mdat generated meta comments, e.g. `+` */
48
- metaCommentIdentifier: string;
49
- };
50
- /**
51
- * Parse an Mdast HTML comment node into structured data.
52
- * @returns A discriminated union of CommentMarkerNode based on comment type, or
53
- * undefined if the node is not a comment.
54
- */
55
- export declare function parseCommentNode(node: Html, parent: Parent, options: CommentMarkerParseOptions): CommentMarkerNode | undefined;
56
- /**
57
- * Parse any comment string into structured data.
58
- * @returns A discriminated union of CommentMarker based on comment type, or
59
- * undefined if the node is not a comment.
60
- */
61
- export declare function parseComment(text: string, options: CommentMarkerParseOptions): CommentMarker | undefined;
62
- export {};
@@ -1,112 +0,0 @@
1
- import type { Root } from 'mdast';
2
- import type { JsonValue, Merge, MergeDeep, SetOptional, Simplify } from 'type-fest';
3
- import { z } from 'zod';
4
- export type SimplifyDeep<T> = Simplify<MergeDeep<T, T>>;
5
- /**
6
- * Strict normalized rules used internally.
7
- * Rules normalized to a form with async content functions and other default metadata
8
- * Simplifies processing elsewhere, while retaining flexibility for rule authors
9
- */
10
- export type NormalizedRule = {
11
- /**
12
- * The order in which the rule should be applied during processing
13
- * Helpful if a rule depends on the presence of content generated by another rule
14
- * Defaults to 0.
15
- */
16
- applicationOrder: number;
17
- /**
18
- * The function that generates the expanded Markdown string.
19
- * For 'compound' rules, this can be an array of rules (without keywords).
20
- */
21
- content: ((options: JsonValue, tree: Root) => Promise<string>) | NormalizedRule[];
22
- /**
23
- * The expected order of the keyword in the document relative to other expander comments.
24
- * Used for validation purposes.
25
- * Leave undefined to order skip validation.
26
- * Defaults to undefined, which means order is not enforced.
27
- */
28
- order: number | undefined;
29
- /**
30
- * Whether the presence of the keyword comment in the document is required.
31
- * Used for validation purposes.
32
- * Defaults to false.
33
- */
34
- required: boolean;
35
- };
36
- export type Rule =
37
- /**
38
- * Function that returns the Markdown string to expand at the comment site.
39
- */
40
- ((options: JsonValue, tree: Root) => Promise<string> | string)
41
- /**
42
- * Compound rules may be defined an array of rules, without keywords.
43
- * Can be defined at the top level, if no validation metadata is required, or as the 'content' value
44
- * of a rule object with validation metadata.
45
- */
46
- | Rule[]
47
- /**
48
- * The Markdown string to expand at the comment site.
49
- */
50
- | SetOptional<Merge<NormalizedRule, {
51
- /**
52
- * Gets content to expand into the comment.
53
- * Can be a simple string for direct replacement, a function that returns a string, or an async function that returns a string.
54
- *
55
- * If a function is provided, it will be passed the following arguments:
56
- * @param options
57
- * JSON value of options parsed immediately after the comment keyword in the comment, e.g.:
58
- * `<!-- keyword({something: true}) -->` or
59
- * `<!-- keyword {something: true}-->`
60
- * Sets options to {something: true}
61
- * @param tree
62
- * Markdown (mdast) abstract syntax tree containing the entire parsed document. Useful for expanders that need the entire document context, such as when generating a table of contents. Do not mutate the AST, instead return a new string.
63
- * @returns A string with the generated content. The string will be parsed as Markdown and inserted into the document at the comment's location.
64
- */
65
- content: ((options: JsonValue, tree: Root) => Promise<string> | string) | Rule[] | string;
66
- }>, 'applicationOrder' | 'order' | 'required'> | string;
67
- /**
68
- * Rules are record objects whose keys match strings inside a Markdown comment, and values explain what should be expanded at the comment site.
69
- *
70
- * The record value may be a string, or an object containing additional metadata, possibly with a function to invoke to generate content.
71
- * @example
72
- * Most basic rule:
73
- * ```ts
74
- * { basic: 'content' }
75
- * ```
76
- *
77
- * Rule with dynamic content:
78
- * ```ts
79
- * { basic: () => `${new Date().toISOString()}` }
80
- * ```
81
- *
82
- * Rule with metadata:
83
- * ```ts
84
- * { basic-meta: { required: true, content: 'content'} }
85
- * ```
86
- *
87
- * Rule with dynamic content and metadata:
88
- * { basic-date: { required: true, content: () => `${new Date().toISOString()}` } }
89
- */
90
- export type Rules = SimplifyDeep<Record<string, Rule>>;
91
- export type NormalizedRules = SimplifyDeep<Record<string, NormalizedRule>>;
92
- export declare function normalizeRules(rules: Rules): NormalizedRules;
93
- export declare function validateRules(rules: Rules): void;
94
- export declare const rulesSchema: z.ZodRecord<z.ZodString, z.ZodType<any, z.ZodTypeDef, any>>;
95
- /**
96
- * Compound rule helpers, used in both "expand" and "check" utilities
97
- */
98
- export declare function getRuleContent(rule: NormalizedRule, options: JsonValue, tree: Root, check?: boolean): Promise<string>;
99
- /**
100
- * Returns the rule value from a single-rule record.
101
- * Useful when aliasing rules or invoking them programmatically.
102
- *
103
- * Throws if there are no entries or more than one entry.
104
- */
105
- export declare function getSoleRule<T extends NormalizedRules | Rules>(rules: T): T[keyof T];
106
- /**
107
- * Returns the rule key from a single-rule record.
108
- * Useful for comment placeholder validation.
109
- *
110
- * Throws if there are no entries or more than one entry.
111
- */
112
- export declare function getSoleRuleKey<T extends NormalizedRules | Rules>(rules: T): keyof T;
@@ -1,29 +0,0 @@
1
- import type { Root } from 'mdast';
2
- import type { Plugin } from 'unified';
3
- import { z } from 'zod';
4
- import type { Options as MdatOptions } from './mdast-utils/mdast-util-mdat';
5
- export type Options = Partial<MdatOptions>;
6
- export declare const optionsSchema: z.ZodObject<{
7
- addMetaComment: z.ZodOptional<z.ZodUnion<[z.ZodBoolean, z.ZodString]>>;
8
- closingPrefix: z.ZodOptional<z.ZodString>;
9
- keywordPrefix: z.ZodOptional<z.ZodString>;
10
- metaCommentIdentifier: z.ZodOptional<z.ZodString>;
11
- rules: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodType<any, z.ZodTypeDef, any>>>;
12
- }, "strip", z.ZodTypeAny, {
13
- closingPrefix?: string | undefined;
14
- keywordPrefix?: string | undefined;
15
- metaCommentIdentifier?: string | undefined;
16
- rules?: Record<string, any> | undefined;
17
- addMetaComment?: string | boolean | undefined;
18
- }, {
19
- closingPrefix?: string | undefined;
20
- keywordPrefix?: string | undefined;
21
- metaCommentIdentifier?: string | undefined;
22
- rules?: Record<string, any> | undefined;
23
- addMetaComment?: string | boolean | undefined;
24
- }>;
25
- /**
26
- * A remark plugin that expands HTML comments in Markdown files.
27
- */
28
- declare const remarkMdat: Plugin<[Options], Root>;
29
- export default remarkMdat;