mdat 2.2.0 → 2.3.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/dist/bin/cli.js CHANGED
@@ -42,7 +42,7 @@ function deepMergeDefined(...objects) {
42
42
  //#endregion
43
43
  //#region package.json
44
44
  var name = "mdat";
45
- var version = "2.2.0";
45
+ var version = "2.3.0";
46
46
 
47
47
  //#endregion
48
48
  //#region src/lib/log.ts
@@ -101,6 +101,7 @@ async function getContextMetadata() {
101
101
  metascopeMetadata = await getMetadata({
102
102
  absolute: false,
103
103
  offline: true,
104
+ recursive: false,
104
105
  sources: [
105
106
  "arduinoLibraryProperties",
106
107
  "cinderCinderblockXml",
@@ -143,17 +144,52 @@ const readmeMetadataTemplate = defineTemplate((context) => {
143
144
  const licenseFileData = helpers.firstOf(licenseFile);
144
145
  const ciActionFilePath = helpers.ensureArray(githubActions).find((entry) => entry.data.name.toLowerCase() === "ci")?.source;
145
146
  const repositoryUrl = codemeta.codeRepository?.replace(GIT_PREFIX_REGEX, "").replace(GIT_SUFFIX_REGEX, "").replace(TRAILING_SLASH_REGEX, "");
147
+ const bin = (() => {
148
+ if (nodePackage === void 0) return;
149
+ const binField = nodePackage.bin;
150
+ if (binField === void 0) return;
151
+ if (typeof binField === "string") return [nodePackage.name];
152
+ const names = Object.keys(binField);
153
+ return names.length > 0 ? names : void 0;
154
+ })();
155
+ const engines = (() => {
156
+ const raw = nodePackage?.engines;
157
+ if (raw === void 0) return;
158
+ const entries = Object.entries(raw).filter((entry) => entry[1] !== void 0);
159
+ return entries.length > 0 ? Object.fromEntries(entries) : void 0;
160
+ })();
161
+ const peerDependencies = (() => {
162
+ if (nodePackage === void 0) return;
163
+ const peers = nodePackage.peerDependencies;
164
+ if (peers === void 0) return;
165
+ const entries = Object.entries(peers).filter((entry) => entry[1] !== void 0);
166
+ if (entries.length === 0) return;
167
+ const meta = nodePackage.peerDependenciesMeta;
168
+ return entries.map(([name, version]) => ({
169
+ name,
170
+ optional: meta?.[name]?.optional === true,
171
+ version
172
+ }));
173
+ })();
174
+ const firstAuthor = helpers.firstOf(helpers.ensureArray(codemeta.author));
146
175
  return {
147
176
  author: helpers.firstOf(helpers.mixedStringsToArray(helpers.toBasicNames(codemeta.author))),
177
+ authorUrl: firstAuthor?.url,
178
+ bin,
148
179
  ciActionFileName: ciActionFilePath ? path.basename(ciActionFilePath) : void 0,
149
180
  description: codemeta.description,
150
- isPublicNpmPackage: !nodePackage?.name.startsWith("@") || nodePackage.publishConfig?.access === "public",
181
+ engines,
182
+ isPublicNpmPackage: nodePackage?.private !== true && (nodePackage?.name.startsWith("@") && nodePackage.publishConfig?.access === "public" || true),
151
183
  issuesUrl: codemeta.issueTracker,
152
184
  license: helpers.toBasicLicense(helpers.firstOf(helpers.ensureArray(codemeta.license))),
153
185
  licenseFilePath: licenseFileData?.source,
154
186
  name: codemeta.name,
187
+ operatingSystem: codemeta.operatingSystem,
188
+ peerDependencies,
155
189
  projectDirectory: metascope?.data.options.path === void 0 ? void 0 : `file://${metascope.data.options.path}`,
156
- repositoryUrl
190
+ repositoryUrl,
191
+ runtimePlatform: codemeta.runtimePlatform,
192
+ usesPnpm: helpers.usesPnpm(nodePackageJson)
157
193
  };
158
194
  });
159
195
  let readmeMetadata;
@@ -277,7 +313,85 @@ var code_default = { code: { async content(options) {
277
313
  var contributing_default = { contributing: { async content() {
278
314
  const { issuesUrl } = await getReadmeMetadata();
279
315
  if (issuesUrl === void 0) throw new Error("Could not find \"bugs.url\" entry in package.json");
280
- return `## Contributing\n[Issues](${issuesUrl}) and pull requests are welcome.`;
316
+ return [
317
+ "## Contributing",
318
+ "",
319
+ `[Issues](${issuesUrl}) are welcome and appreciated.`,
320
+ "",
321
+ "Please open an issue to discuss changes before submitting a pull request. Unsolicited PRs (especially AI-generated ones) are unlikely to be merged.",
322
+ "",
323
+ "This repository uses [@kitschpatrol/shared-config](https://github.com/kitschpatrol/shared-config) (via its `ksc` CLI) for linting and formatting, plus [MDAT](https://github.com/kitschpatrol/mdat) for readme placeholder expansion."
324
+ ].join("\n");
325
+ } } };
326
+
327
+ //#endregion
328
+ //#region src/lib/readme/rules/dependencies.ts
329
+ const PLATFORM_INFO = {
330
+ bun: {
331
+ display: "Bun",
332
+ url: "https://bun.sh/"
333
+ },
334
+ deno: {
335
+ display: "Deno",
336
+ url: "https://deno.land/"
337
+ },
338
+ go: {
339
+ display: "Go",
340
+ url: "https://go.dev/"
341
+ },
342
+ java: {
343
+ display: "Java",
344
+ url: "https://www.java.com/"
345
+ },
346
+ node: {
347
+ display: "Node.js",
348
+ url: "https://nodejs.org/"
349
+ },
350
+ python: {
351
+ display: "Python",
352
+ url: "https://www.python.org/"
353
+ },
354
+ ruby: {
355
+ display: "Ruby",
356
+ url: "https://www.ruby-lang.org/"
357
+ },
358
+ rust: {
359
+ display: "Rust",
360
+ url: "https://www.rust-lang.org/"
361
+ }
362
+ };
363
+ var dependencies_default = { dependencies: { async content() {
364
+ const { engines, operatingSystem, peerDependencies, runtimePlatform } = await getReadmeMetadata();
365
+ const platformItems = [];
366
+ if (engines !== void 0) for (const [name, version] of Object.entries(engines)) {
367
+ const info = PLATFORM_INFO[name.toLowerCase()];
368
+ const display = info ? `[${info.display}](${info.url})` : name;
369
+ platformItems.push(`- ${display} ${version}`);
370
+ }
371
+ if (runtimePlatform !== void 0) for (const entry of runtimePlatform) {
372
+ const spaceIndex = entry.indexOf(" ");
373
+ const platformKey = spaceIndex > 0 ? entry.slice(0, spaceIndex) : entry;
374
+ const version = spaceIndex > 0 ? entry.slice(spaceIndex + 1) : void 0;
375
+ if (engines?.[platformKey] !== void 0) continue;
376
+ const info = PLATFORM_INFO[platformKey.toLowerCase()];
377
+ const display = info ? `[${info.display}](${info.url})` : platformKey;
378
+ platformItems.push(version ? `- ${display} ${version}` : `- ${display}`);
379
+ }
380
+ if (operatingSystem !== void 0 && operatingSystem.length > 0) platformItems.push(`- Supported platforms: ${operatingSystem.join(", ")}`);
381
+ const peerItems = [];
382
+ if (peerDependencies !== void 0) for (const { name, optional, version } of peerDependencies) {
383
+ const npmUrl = `https://www.npmjs.com/package/${name}`;
384
+ const optionalSuffix = optional ? " _(optional)_" : "";
385
+ peerItems.push(`- [${name}](${npmUrl}) ${version}${optionalSuffix}`);
386
+ }
387
+ const hasPlatform = platformItems.length > 0;
388
+ const hasPeers = peerItems.length > 0;
389
+ if (!hasPlatform && !hasPeers) return "";
390
+ const sections = ["## Dependencies"];
391
+ if (hasPlatform && hasPeers) sections.push("", "### Platform", "", ...platformItems, "", "### Peer Dependencies", "", ...peerItems);
392
+ else if (hasPlatform) sections.push("", ...platformItems);
393
+ else sections.push("", ...peerItems);
394
+ return sections.join("\n");
281
395
  } } };
282
396
 
283
397
  //#endregion
@@ -294,10 +408,10 @@ var description_default = { description: { async content() {
294
408
  //#endregion
295
409
  //#region src/lib/readme/rules/license.ts
296
410
  var license_default = { license: { async content() {
297
- const { author, license, licenseFilePath } = await getReadmeMetadata();
411
+ const { author, authorUrl, license, licenseFilePath } = await getReadmeMetadata();
298
412
  if (author === void 0) throw new Error("Could not find author name in project");
299
413
  if (license === void 0 || licenseFilePath === void 0) throw new Error("Could not find license for project");
300
- return `## License\n[${license}](${licenseFilePath}) © ${author}`;
414
+ return `## License\n[${license}](${licenseFilePath}) © ${authorUrl === void 0 ? author : `[${author}](${authorUrl})`}`;
301
415
  } } };
302
416
 
303
417
  //#endregion
@@ -345,6 +459,25 @@ var header_default = { header: {
345
459
  order: 2
346
460
  } };
347
461
 
462
+ //#endregion
463
+ //#region src/lib/readme/rules/install.ts
464
+ var install_default = { install: { async content() {
465
+ const { bin, engines, isPublicNpmPackage, name, runtimePlatform, usesPnpm } = await getReadmeMetadata();
466
+ if (name === void 0) throw new Error("Could not find project name");
467
+ const lines = ["## Install"];
468
+ if (isPublicNpmPackage || engines?.node !== void 0 || runtimePlatform?.includes("node")) {
469
+ const pmAdd = usesPnpm ? "pnpm add" : "npm install";
470
+ const pmx = usesPnpm ? "pnpx" : "npx";
471
+ lines.push("", "```sh", `${pmAdd} ${name}`, "```");
472
+ if (bin !== void 0 && bin.length > 0) lines.push("", "Or run it directly:", "", "```sh", `${pmx} ${name}`, "```");
473
+ } else if (runtimePlatform?.some((p) => p.startsWith("python"))) lines.push("", "```sh", `pip install ${name}`, "```");
474
+ else if (runtimePlatform?.some((p) => p.startsWith("rust"))) lines.push("", "```sh", `cargo install ${name}`, "```");
475
+ else if (runtimePlatform?.some((p) => p.startsWith("go"))) lines.push("", "```sh", `go install ${name}@latest`, "```");
476
+ else if (runtimePlatform?.some((p) => p.startsWith("ruby"))) lines.push("", "```sh", `gem install ${name}`, "```");
477
+ else throw new Error("Could not determine project ecosystem for install instructions");
478
+ return lines.join("\n");
479
+ } } };
480
+
348
481
  //#endregion
349
482
  //#region src/lib/readme/rules/utilities/size/size-report.ts
350
483
  const brotliCompressAsync = promisify(brotliCompress);
@@ -503,9 +636,11 @@ var rules_default = {
503
636
  ...banner_default,
504
637
  ...code_default,
505
638
  ...contributing_default,
639
+ ...dependencies_default,
506
640
  ...description_default,
507
641
  ...footer_default,
508
642
  ...header_default,
643
+ ...install_default,
509
644
  ...license_default,
510
645
  ...short_description_default,
511
646
  ...size_default,
@@ -531,9 +666,9 @@ function getAdditionalConfigExplorer() {
531
666
  return _additionalConfigExplorer;
532
667
  }
533
668
  /**
534
- * Load and validate mdat configuration.
535
- * Uses cosmiconfig to search in the usual places.
536
- * Merge precedence: Base Defaults < Defaults < Searched Config < Additional Config
669
+ * Load and validate mdat configuration. Uses cosmiconfig to search in the usual
670
+ * places. Merge precedence: Base Defaults < Defaults < Searched Config <
671
+ * Additional Config
537
672
  */
538
673
  async function loadConfig(options) {
539
674
  const { additionalConfig, defaults = rules_default, searchFrom } = options ?? {};
@@ -6,39 +6,43 @@ import { VFile } from "vfile";
6
6
 
7
7
  //#region src/lib/config.d.ts
8
8
  /**
9
- * An mdat configuration is a record of expansion rules.
10
- * Keys become comment keywords, values define the expansion content.
9
+ * An mdat configuration is a record of expansion rules. Keys become comment
10
+ * keywords, values define the expansion content.
11
11
  */
12
12
  type Config = Record<string, Rule$1>;
13
13
  /**
14
- * Generously accept either string paths to .ts, .js, or .json config files,
15
- * or inline Config objects.
14
+ * Generously accept either string paths to .ts, .js, or .json config files, or
15
+ * inline Config objects.
16
16
  */
17
17
  type ConfigToLoad = Array<Config | string> | Config | string;
18
18
  /**
19
- * Load and validate mdat configuration.
20
- * Uses cosmiconfig to search in the usual places.
21
- * Merge precedence: Base Defaults < Defaults < Searched Config < Additional Config
19
+ * Load and validate mdat configuration. Uses cosmiconfig to search in the usual
20
+ * places. Merge precedence: Base Defaults < Defaults < Searched Config <
21
+ * Additional Config
22
22
  */
23
23
  declare function loadConfig(options?: {
24
24
  /**
25
25
  * Additional Config objects to merge.
26
26
  *
27
- * Strings are treated as paths to `ts`, `js`, or `json` config files.
28
- * These will be dynamically loaded by Cosmiconfig.
29
- * Accepts an individual item, or an array. Objects in the array will be merged right to left.
27
+ * Strings are treated as paths to `ts`, `js`, or `json` config files. These
28
+ * will be dynamically loaded by Cosmiconfig. Accepts an individual item, or
29
+ * an array. Objects in the array will be merged right to left.
30
30
  */
31
31
  additionalConfig?: ConfigToLoad;
32
32
  /**
33
- * Default rules that have higher priority than base defaults but lower than searched config.
34
- * Defaults to the built-in readme rules. Pass `{}` to disable.
33
+ * Default rules that have higher priority than base defaults but lower than
34
+ * searched config. Defaults to the built-in readme rules. Pass `{}` to
35
+ * disable.
36
+ */
37
+ defaults?: Config;
38
+ /**
39
+ * Search for config in specific directories, mainly useful for testing.
40
+ * Cosmiconfig default search paths used if unset.
35
41
  */
36
- defaults?: Config; /** Search for config in specific directories, mainly useful for testing. Cosmiconfig default search paths used if unset. */
37
42
  searchFrom?: string;
38
43
  }): Promise<Config>;
39
44
  /**
40
- * Convenience function for merging configs.
41
- * Rightmost config takes precedence.
45
+ * Convenience function for merging configs. Rightmost config takes precedence.
42
46
  */
43
47
  declare function mergeConfig(a: Config, b: Config): Config;
44
48
  /**
@@ -148,15 +152,28 @@ declare function checkString(markdown: string, config?: ConfigToLoad, options?:
148
152
  declare function getContextMetadata(): Promise<MetadataContext>;
149
153
  declare const readmeMetadataTemplate: _$metascope.Template<{
150
154
  author: string | undefined;
155
+ authorUrl: string | undefined;
156
+ bin: string[] | undefined;
151
157
  ciActionFileName: string | undefined;
152
158
  description: string | undefined;
159
+ engines: {
160
+ [k: string]: string;
161
+ } | undefined;
153
162
  isPublicNpmPackage: boolean;
154
163
  issuesUrl: string | undefined;
155
164
  license: string | undefined;
156
165
  licenseFilePath: string | undefined;
157
166
  name: string | undefined;
167
+ operatingSystem: string[] | undefined;
168
+ peerDependencies: {
169
+ name: string;
170
+ optional: boolean;
171
+ version: string;
172
+ }[] | undefined;
158
173
  projectDirectory: string | undefined;
159
174
  repositoryUrl: string | undefined;
175
+ runtimePlatform: string[] | undefined;
176
+ usesPnpm: boolean;
160
177
  }>;
161
178
  type ReadmeMetadata = ReturnType<typeof readmeMetadataTemplate>;
162
179
  /**
@@ -166,15 +183,28 @@ type ReadmeMetadata = ReturnType<typeof readmeMetadataTemplate>;
166
183
  */
167
184
  declare function getReadmeMetadata(): Promise<{
168
185
  author: string | undefined;
186
+ authorUrl: string | undefined;
187
+ bin: string[] | undefined;
169
188
  ciActionFileName: string | undefined;
170
189
  description: string | undefined;
190
+ engines: {
191
+ [k: string]: string;
192
+ } | undefined;
171
193
  isPublicNpmPackage: boolean;
172
194
  issuesUrl: string | undefined;
173
195
  license: string | undefined;
174
196
  licenseFilePath: string | undefined;
175
197
  name: string | undefined;
198
+ operatingSystem: string[] | undefined;
199
+ peerDependencies: {
200
+ name: string;
201
+ optional: boolean;
202
+ version: string;
203
+ }[] | undefined;
176
204
  projectDirectory: string | undefined;
177
205
  repositoryUrl: string | undefined;
206
+ runtimePlatform: string[] | undefined;
207
+ usesPnpm: boolean;
178
208
  }>;
179
209
  /**
180
210
  * Reset all cached metadata. Call between tests or when the underlying project
@@ -188,6 +218,6 @@ declare function resetMetadataCaches(): void;
188
218
  * Export this for library consumers to inject their own logger.
189
219
  * @param logger - Accepts either a LogLayer instance or a Console- or Stream-like log target
190
220
  */
191
- declare function setLogger(logger?: ILogBasic | ILogLayer): void;
221
+ declare function setLogger(logger?: ILogBasic | ILogLayer<unknown>): void;
192
222
  //#endregion
193
223
  export { type Config, type ReadmeMetadata, type Rule, check, checkString, collapse, collapseString, createReadme as create, createReadmeInteractive as createInteractive, defineConfig, expand, expandString, getContextMetadata, getReadmeMetadata, loadConfig, mergeConfig, resetMetadataCaches, setLogger, strip, stripString };
package/dist/lib/index.js CHANGED
@@ -88,6 +88,7 @@ async function getContextMetadata() {
88
88
  metascopeMetadata = await getMetadata({
89
89
  absolute: false,
90
90
  offline: true,
91
+ recursive: false,
91
92
  sources: [
92
93
  "arduinoLibraryProperties",
93
94
  "cinderCinderblockXml",
@@ -139,17 +140,52 @@ const readmeMetadataTemplate = defineTemplate((context) => {
139
140
  const licenseFileData = helpers.firstOf(licenseFile);
140
141
  const ciActionFilePath = helpers.ensureArray(githubActions).find((entry) => entry.data.name.toLowerCase() === "ci")?.source;
141
142
  const repositoryUrl = codemeta.codeRepository?.replace(GIT_PREFIX_REGEX, "").replace(GIT_SUFFIX_REGEX, "").replace(TRAILING_SLASH_REGEX, "");
143
+ const bin = (() => {
144
+ if (nodePackage === void 0) return;
145
+ const binField = nodePackage.bin;
146
+ if (binField === void 0) return;
147
+ if (typeof binField === "string") return [nodePackage.name];
148
+ const names = Object.keys(binField);
149
+ return names.length > 0 ? names : void 0;
150
+ })();
151
+ const engines = (() => {
152
+ const raw = nodePackage?.engines;
153
+ if (raw === void 0) return;
154
+ const entries = Object.entries(raw).filter((entry) => entry[1] !== void 0);
155
+ return entries.length > 0 ? Object.fromEntries(entries) : void 0;
156
+ })();
157
+ const peerDependencies = (() => {
158
+ if (nodePackage === void 0) return;
159
+ const peers = nodePackage.peerDependencies;
160
+ if (peers === void 0) return;
161
+ const entries = Object.entries(peers).filter((entry) => entry[1] !== void 0);
162
+ if (entries.length === 0) return;
163
+ const meta = nodePackage.peerDependenciesMeta;
164
+ return entries.map(([name, version]) => ({
165
+ name,
166
+ optional: meta?.[name]?.optional === true,
167
+ version
168
+ }));
169
+ })();
170
+ const firstAuthor = helpers.firstOf(helpers.ensureArray(codemeta.author));
142
171
  return {
143
172
  author: helpers.firstOf(helpers.mixedStringsToArray(helpers.toBasicNames(codemeta.author))),
173
+ authorUrl: firstAuthor?.url,
174
+ bin,
144
175
  ciActionFileName: ciActionFilePath ? path.basename(ciActionFilePath) : void 0,
145
176
  description: codemeta.description,
146
- isPublicNpmPackage: !nodePackage?.name.startsWith("@") || nodePackage.publishConfig?.access === "public",
177
+ engines,
178
+ isPublicNpmPackage: nodePackage?.private !== true && (nodePackage?.name.startsWith("@") && nodePackage.publishConfig?.access === "public" || true),
147
179
  issuesUrl: codemeta.issueTracker,
148
180
  license: helpers.toBasicLicense(helpers.firstOf(helpers.ensureArray(codemeta.license))),
149
181
  licenseFilePath: licenseFileData?.source,
150
182
  name: codemeta.name,
183
+ operatingSystem: codemeta.operatingSystem,
184
+ peerDependencies,
151
185
  projectDirectory: metascope?.data.options.path === void 0 ? void 0 : `file://${metascope.data.options.path}`,
152
- repositoryUrl
186
+ repositoryUrl,
187
+ runtimePlatform: codemeta.runtimePlatform,
188
+ usesPnpm: helpers.usesPnpm(nodePackageJson)
153
189
  };
154
190
  });
155
191
  let readmeMetadata;
@@ -286,7 +322,84 @@ var code_default = { code: { async content(options) {
286
322
  var contributing_default = { contributing: { async content() {
287
323
  const { issuesUrl } = await getReadmeMetadata();
288
324
  if (issuesUrl === void 0) throw new Error("Could not find \"bugs.url\" entry in package.json");
289
- return `## Contributing\n[Issues](${issuesUrl}) and pull requests are welcome.`;
325
+ return [
326
+ "## Contributing",
327
+ "",
328
+ `[Issues](${issuesUrl}) are welcome and appreciated.`,
329
+ "",
330
+ "Please open an issue to discuss changes before submitting a pull request. Unsolicited PRs (especially AI-generated ones) are unlikely to be merged.",
331
+ "",
332
+ "This repository uses [@kitschpatrol/shared-config](https://github.com/kitschpatrol/shared-config) (via its `ksc` CLI) for linting and formatting, plus [MDAT](https://github.com/kitschpatrol/mdat) for readme placeholder expansion."
333
+ ].join("\n");
334
+ } } };
335
+ //#endregion
336
+ //#region src/lib/readme/rules/dependencies.ts
337
+ const PLATFORM_INFO = {
338
+ bun: {
339
+ display: "Bun",
340
+ url: "https://bun.sh/"
341
+ },
342
+ deno: {
343
+ display: "Deno",
344
+ url: "https://deno.land/"
345
+ },
346
+ go: {
347
+ display: "Go",
348
+ url: "https://go.dev/"
349
+ },
350
+ java: {
351
+ display: "Java",
352
+ url: "https://www.java.com/"
353
+ },
354
+ node: {
355
+ display: "Node.js",
356
+ url: "https://nodejs.org/"
357
+ },
358
+ python: {
359
+ display: "Python",
360
+ url: "https://www.python.org/"
361
+ },
362
+ ruby: {
363
+ display: "Ruby",
364
+ url: "https://www.ruby-lang.org/"
365
+ },
366
+ rust: {
367
+ display: "Rust",
368
+ url: "https://www.rust-lang.org/"
369
+ }
370
+ };
371
+ var dependencies_default = { dependencies: { async content() {
372
+ const { engines, operatingSystem, peerDependencies, runtimePlatform } = await getReadmeMetadata();
373
+ const platformItems = [];
374
+ if (engines !== void 0) for (const [name, version] of Object.entries(engines)) {
375
+ const info = PLATFORM_INFO[name.toLowerCase()];
376
+ const display = info ? `[${info.display}](${info.url})` : name;
377
+ platformItems.push(`- ${display} ${version}`);
378
+ }
379
+ if (runtimePlatform !== void 0) for (const entry of runtimePlatform) {
380
+ const spaceIndex = entry.indexOf(" ");
381
+ const platformKey = spaceIndex > 0 ? entry.slice(0, spaceIndex) : entry;
382
+ const version = spaceIndex > 0 ? entry.slice(spaceIndex + 1) : void 0;
383
+ if (engines?.[platformKey] !== void 0) continue;
384
+ const info = PLATFORM_INFO[platformKey.toLowerCase()];
385
+ const display = info ? `[${info.display}](${info.url})` : platformKey;
386
+ platformItems.push(version ? `- ${display} ${version}` : `- ${display}`);
387
+ }
388
+ if (operatingSystem !== void 0 && operatingSystem.length > 0) platformItems.push(`- Supported platforms: ${operatingSystem.join(", ")}`);
389
+ const peerItems = [];
390
+ if (peerDependencies !== void 0) for (const { name, optional, version } of peerDependencies) {
391
+ const npmUrl = `https://www.npmjs.com/package/${name}`;
392
+ const optionalSuffix = optional ? " _(optional)_" : "";
393
+ peerItems.push(`- [${name}](${npmUrl}) ${version}${optionalSuffix}`);
394
+ }
395
+ const hasPlatform = platformItems.length > 0;
396
+ const hasPeers = peerItems.length > 0;
397
+ if (!hasPlatform && !hasPeers) return "";
398
+ const sections = ["## Dependencies"];
399
+ if (hasPlatform && hasPeers) sections.push("", "### Platform", "", ...platformItems, "", "### Peer Dependencies", "", ...peerItems);
400
+ else if (hasPlatform) sections.push("", ...platformItems);
401
+ else sections.push("", ...peerItems);
402
+ return sections.join("\n");
290
403
  } } };
291
404
  //#endregion
292
405
  //#region src/lib/readme/rules/description.ts
@@ -301,10 +414,10 @@ var description_default = { description: { async content() {
301
414
  //#endregion
302
415
  //#region src/lib/readme/rules/license.ts
303
416
  var license_default = { license: { async content() {
304
- const { author, license, licenseFilePath } = await getReadmeMetadata();
417
+ const { author, authorUrl, license, licenseFilePath } = await getReadmeMetadata();
305
418
  if (author === void 0) throw new Error("Could not find author name in project");
306
419
  if (license === void 0 || licenseFilePath === void 0) throw new Error("Could not find license for project");
307
- return `## License\n[${license}](${licenseFilePath}) © ${author}`;
420
+ return `## License\n[${license}](${licenseFilePath}) © ${authorUrl === void 0 ? author : `[${author}](${authorUrl})`}`;
308
421
  } } };
309
422
  //#endregion
310
423
  //#region src/lib/readme/rules/footer.ts
@@ -348,6 +461,24 @@ var header_default = { header: {
348
461
  order: 2
349
462
  } };
350
463
  //#endregion
464
+ //#region src/lib/readme/rules/install.ts
465
+ var install_default = { install: { async content() {
466
+ const { bin, engines, isPublicNpmPackage, name, runtimePlatform, usesPnpm } = await getReadmeMetadata();
467
+ if (name === void 0) throw new Error("Could not find project name");
468
+ const lines = ["## Install"];
469
+ if (isPublicNpmPackage || engines?.node !== void 0 || runtimePlatform?.includes("node")) {
470
+ const pmAdd = usesPnpm ? "pnpm add" : "npm install";
471
+ const pmx = usesPnpm ? "pnpx" : "npx";
472
+ lines.push("", "```sh", `${pmAdd} ${name}`, "```");
473
+ if (bin !== void 0 && bin.length > 0) lines.push("", "Or run it directly:", "", "```sh", `${pmx} ${name}`, "```");
474
+ } else if (runtimePlatform?.some((p) => p.startsWith("python"))) lines.push("", "```sh", `pip install ${name}`, "```");
475
+ else if (runtimePlatform?.some((p) => p.startsWith("rust"))) lines.push("", "```sh", `cargo install ${name}`, "```");
476
+ else if (runtimePlatform?.some((p) => p.startsWith("go"))) lines.push("", "```sh", `go install ${name}@latest`, "```");
477
+ else if (runtimePlatform?.some((p) => p.startsWith("ruby"))) lines.push("", "```sh", `gem install ${name}`, "```");
478
+ else throw new Error("Could not determine project ecosystem for install instructions");
479
+ return lines.join("\n");
480
+ } } };
481
+ //#endregion
351
482
  //#region src/lib/readme/rules/utilities/size/size-report.ts
352
483
  const brotliCompressAsync = promisify(brotliCompress);
353
484
  const gzipCompressAsync = promisify(gzip);
@@ -500,9 +631,11 @@ var rules_default = {
500
631
  ...banner_default,
501
632
  ...code_default,
502
633
  ...contributing_default,
634
+ ...dependencies_default,
503
635
  ...description_default,
504
636
  ...footer_default,
505
637
  ...header_default,
638
+ ...install_default,
506
639
  ...license_default,
507
640
  ...short_description_default,
508
641
  ...size_default,
@@ -527,9 +660,9 @@ function getAdditionalConfigExplorer() {
527
660
  return _additionalConfigExplorer;
528
661
  }
529
662
  /**
530
- * Load and validate mdat configuration.
531
- * Uses cosmiconfig to search in the usual places.
532
- * Merge precedence: Base Defaults < Defaults < Searched Config < Additional Config
663
+ * Load and validate mdat configuration. Uses cosmiconfig to search in the usual
664
+ * places. Merge precedence: Base Defaults < Defaults < Searched Config <
665
+ * Additional Config
533
666
  */
534
667
  async function loadConfig(options) {
535
668
  const { additionalConfig, defaults = rules_default, searchFrom } = options ?? {};
@@ -580,8 +713,7 @@ function validateConfig(value) {
580
713
  log.warn(`Config has the wrong shape. Ignoring and using default configuration:\n${JSON.stringify(value, void 0, 2)}`);
581
714
  }
582
715
  /**
583
- * Convenience function for merging configs.
584
- * Rightmost config takes precedence.
716
+ * Convenience function for merging configs. Rightmost config takes precedence.
585
717
  */
586
718
  function mergeConfig(a, b) {
587
719
  return deepMergeDefined(a, b);
@@ -774,46 +906,28 @@ function getStripProcessor(_config, ambientRemarkConfig) {
774
906
  });
775
907
  }
776
908
  //#endregion
777
- //#region src/lib/readme/templates/mdat-readme-compound.md?raw
778
- var mdat_readme_compound_default = "<!-- header -->\n\n<!-- table-of-contents -->\n\n## Overview\n\n## Getting started\n\n### Dependencies\n\n### Installation\n\n## Usage\n\n### Library\n\n#### API\n\n#### Examples\n\n### CLI\n\n#### Commands\n\n#### Examples\n\n## Background\n\n### Motivation\n\n### Implementation notes\n\n### Similar projects\n\n## The future\n\n## Maintainers\n\n_List maintainer(s) for a repository, along with one way of contacting them (e.g. GitHub link or email)._\n\n## Acknowledgments\n\n_State anyone or anything that significantly helped with the development of your project. State public contact hyper-links if applicable._\n\n<!-- footer -->\n";
779
- //#endregion
780
- //#region src/lib/readme/templates/mdat-readme.md?raw
781
- var mdat_readme_default = "<!-- title -->\n\n<!-- banner -->\n\n<!-- badges -->\n\n<!-- short-description -->\n\n<!-- table-of-contents -->\n\n## Overview\n\n## Getting started\n\n### Dependencies\n\n### Installation\n\n## Usage\n\n### Library\n\n#### API\n\n#### Examples\n\n### CLI\n\n#### Commands\n\n#### Examples\n\n## Background\n\n### Motivation\n\n### Implementation notes\n\n### Similar projects\n\n## The future\n\n## Maintainers\n\n_List maintainer(s) for a repository, along with one way of contacting them (e.g. GitHub link or email)._\n\n## Acknowledgments\n\n_State anyone or anything that significantly helped with the development of your project. State public contact hyper-links if applicable._\n\n<!-- contributing -->\n\n<!-- license -->\n";
782
- //#endregion
783
- //#region src/lib/readme/templates/standard-readme-basic-compound.md?raw
784
- var standard_readme_basic_compound_default = "<!-- header -->\n\n## Install\n\n```sh\n# Code block illustrating how to install.\n```\n\n## Usage\n\n```ts\n// Code block illustrating common usage.\n// Consider using the <!-- code({ src: \"path/to/example.ts\" }) --> comment as well.\n```\n\n<!-- footer -->\n";
785
- //#endregion
786
- //#region src/lib/readme/templates/standard-readme-basic.md?raw
787
- var standard_readme_basic_default = "<!-- title -->\n\n<!-- short-description -->\n\n<!-- table-of-contents -->\n\n## Install\n\n```sh\n# Code block illustrating how to install.\n```\n\n## Usage\n\n```ts\n// Code block illustrating common usage.\n// Consider using the <!-- code({ src: \"path/to/example.ts\" })--> comment as well.\n```\n\n<!-- contributing -->\n\n<!-- license -->\n";
788
- //#endregion
789
- //#region src/lib/readme/templates/standard-readme-full-compound.md?raw
790
- var standard_readme_full_compound_default = "<!-- header -->\n\n_Long description goes here._\n\n_No heading. Cover the main reasons for building the repository. This should describe your module in broad terms, generally in just a few paragraphs; more detail of the module's routines or methods, lengthy code examples, or other in-depth material should be given in subsequent sections._\n\n<!-- table-of-contents -->\n\n## Background\n\n_Cover motivation. Cover abstract dependencies. Cover intellectual provenance: A See Also section is also fitting._\n\n### See also\n\n## Install\n\n```sh\n# Code block illustrating how to install.\n```\n\n### Dependencies\n\n_Required if there are unusual dependencies or dependencies that must be manually installed._\n\n## Usage\n\n```ts\n// Code block illustrating common usage.\n// Consider using the <!-- code({ src: \"path/to/example.ts\" })--> comment as well.\n```\n\n```ts\n// If importable, code block indicating both import functionality and usage.\n```\n\n### CLI\n\n```ts\n// If CLI compatible, code block indicating common usage.\n```\n\n## _Extra Sections (Rename)_\n\n## Security\n\n## API\n\n_Describe exported functions and objects._\n\n- _Describe signatures, return types, callbacks, and events._\n- _Cover types covered where not obvious._\n- _Describe caveats._\n- _If using an external API generator (like go-doc, js-doc, or so on), point to an external API.md file. This can be the only item in the section, if present._\n\n## Maintainers\n\n_List maintainer(s) for a repository, along with one way of contacting them (e.g. GitHub link or email)._\n\n## Thanks\n\n_State anyone or anything that significantly helped with the development of your project. State public contact hyper-links if applicable._\n\n<!-- footer -->\n";
791
- //#endregion
792
- //#region src/lib/readme/templates/standard-readme-full.md?raw
793
- var standard_readme_full_default = "<!-- title -->\n\n<!-- banner -->\n\n<!-- badges -->\n\n<!-- short-description -->\n\n_Long description goes here._\n\n_No heading. Cover the main reasons for building the repository. This should describe your module in broad terms, generally in just a few paragraphs; more detail of the module's routines or methods, lengthy code examples, or other in-depth material should be given in subsequent sections._\n\n<!-- table-of-contents -->\n\n## Background\n\n_Cover motivation. Cover abstract dependencies. Cover intellectual provenance: A See Also section is also fitting._\n\n### See also\n\n## Install\n\n```sh\n# Code block illustrating how to install.\n```\n\n### Dependencies\n\n_Required if there are unusual dependencies or dependencies that must be manually installed._\n\n## Usage\n\n```ts\n// Code block illustrating common usage.\n// Consider using the <!-- code({ src: \"path/to/example.ts\" })--> comment as well.\n```\n\n```ts\n// If importable, code block indicating both import functionality and usage.\n```\n\n### CLI\n\n```ts\n// If CLI compatible, code block indicating common usage.\n```\n\n## _Extra Sections (Rename)_\n\n## Security\n\n## API\n\n_Describe exported functions and objects._\n\n- _Describe signatures, return types, callbacks, and events._\n- _Cover types covered where not obvious._\n- _Describe caveats._\n- _If using an external API generator (like go-doc, js-doc, or so on), point to an external API.md file. This can be the only item in the section, if present._\n\n## Maintainers\n\n_List maintainer(s) for a repository, along with one way of contacting them (e.g. GitHub link or email)._\n\n## Thanks\n\n_State anyone or anything that significantly helped with the development of your project. State public contact hyper-links if applicable._\n\n<!-- contributing -->\n\n<!-- license -->\n";
794
- //#endregion
795
909
  //#region src/lib/readme/templates/index.ts
796
910
  var templates_default = {
797
911
  "MDAT Readme": {
798
912
  content: {
799
- compound: mdat_readme_compound_default,
800
- explicit: mdat_readme_default
913
+ compound: "<!-- header -->\n\n<!-- table-of-contents -->\n\n## Overview\n\n## Getting started\n\n### Dependencies\n\n### Installation\n\n## Usage\n\n### Library\n\n#### API\n\n#### Examples\n\n### CLI\n\n#### Commands\n\n#### Examples\n\n## Background\n\n### Motivation\n\n### Implementation notes\n\n### Similar projects\n\n## The future\n\n## Maintainers\n\n_List maintainer(s) for a repository, along with one way of contacting them (e.g. GitHub link or email)._\n\n## Acknowledgments\n\n_State anyone or anything that significantly helped with the development of your project. State public contact hyper-links if applicable._\n\n<!-- footer -->\n",
914
+ explicit: "<!-- title -->\n\n<!-- banner -->\n\n<!-- badges -->\n\n<!-- short-description -->\n\n<!-- table-of-contents -->\n\n## Overview\n\n## Getting started\n\n### Dependencies\n\n### Installation\n\n## Usage\n\n### Library\n\n#### API\n\n#### Examples\n\n### CLI\n\n#### Commands\n\n#### Examples\n\n## Background\n\n### Motivation\n\n### Implementation notes\n\n### Similar projects\n\n## The future\n\n## Maintainers\n\n_List maintainer(s) for a repository, along with one way of contacting them (e.g. GitHub link or email)._\n\n## Acknowledgments\n\n_State anyone or anything that significantly helped with the development of your project. State public contact hyper-links if applicable._\n\n<!-- contributing -->\n\n<!-- license -->\n"
801
915
  },
802
916
  description: "The house style. An expansive starting point. Prune to your context and taste.",
803
917
  exampleLink: "https://github.com/kitschpatrol/mdat/blob/main/readme.md"
804
918
  },
805
919
  "Standard Readme Basic": {
806
920
  content: {
807
- compound: standard_readme_basic_compound_default,
808
- explicit: standard_readme_basic_default
921
+ compound: "<!-- header -->\n\n## Install\n\n```sh\n# Code block illustrating how to install.\n```\n\n## Usage\n\n```ts\n// Code block illustrating common usage.\n// Consider using the <!-- code({ src: \"path/to/example.ts\" }) --> comment as well.\n```\n\n<!-- footer -->\n",
922
+ explicit: "<!-- title -->\n\n<!-- short-description -->\n\n<!-- table-of-contents -->\n\n## Install\n\n```sh\n# Code block illustrating how to install.\n```\n\n## Usage\n\n```ts\n// Code block illustrating common usage.\n// Consider using the <!-- code({ src: \"path/to/example.ts\" })--> comment as well.\n```\n\n<!-- contributing -->\n\n<!-- license -->\n"
809
923
  },
810
924
  description: "Includes only the \"required\" sections from the Standard Readme specification.",
811
925
  exampleLink: "https://github.com/RichardLitt/standard-readme/blob/main/example-readmes/minimal-readme.md"
812
926
  },
813
927
  "Standard Readme Full": {
814
928
  content: {
815
- compound: standard_readme_full_compound_default,
816
- explicit: standard_readme_full_default
929
+ compound: "<!-- header -->\n\n_Long description goes here._\n\n_No heading. Cover the main reasons for building the repository. This should describe your module in broad terms, generally in just a few paragraphs; more detail of the module's routines or methods, lengthy code examples, or other in-depth material should be given in subsequent sections._\n\n<!-- table-of-contents -->\n\n## Background\n\n_Cover motivation. Cover abstract dependencies. Cover intellectual provenance: A See Also section is also fitting._\n\n### See also\n\n## Install\n\n```sh\n# Code block illustrating how to install.\n```\n\n### Dependencies\n\n_Required if there are unusual dependencies or dependencies that must be manually installed._\n\n## Usage\n\n```ts\n// Code block illustrating common usage.\n// Consider using the <!-- code({ src: \"path/to/example.ts\" })--> comment as well.\n```\n\n```ts\n// If importable, code block indicating both import functionality and usage.\n```\n\n### CLI\n\n```ts\n// If CLI compatible, code block indicating common usage.\n```\n\n## _Extra Sections (Rename)_\n\n## Security\n\n## API\n\n_Describe exported functions and objects._\n\n- _Describe signatures, return types, callbacks, and events._\n- _Cover types covered where not obvious._\n- _Describe caveats._\n- _If using an external API generator (like go-doc, js-doc, or so on), point to an external API.md file. This can be the only item in the section, if present._\n\n## Maintainers\n\n_List maintainer(s) for a repository, along with one way of contacting them (e.g. GitHub link or email)._\n\n## Thanks\n\n_State anyone or anything that significantly helped with the development of your project. State public contact hyper-links if applicable._\n\n<!-- footer -->\n",
930
+ explicit: "<!-- title -->\n\n<!-- banner -->\n\n<!-- badges -->\n\n<!-- short-description -->\n\n_Long description goes here._\n\n_No heading. Cover the main reasons for building the repository. This should describe your module in broad terms, generally in just a few paragraphs; more detail of the module's routines or methods, lengthy code examples, or other in-depth material should be given in subsequent sections._\n\n<!-- table-of-contents -->\n\n## Background\n\n_Cover motivation. Cover abstract dependencies. Cover intellectual provenance: A See Also section is also fitting._\n\n### See also\n\n## Install\n\n```sh\n# Code block illustrating how to install.\n```\n\n### Dependencies\n\n_Required if there are unusual dependencies or dependencies that must be manually installed._\n\n## Usage\n\n```ts\n// Code block illustrating common usage.\n// Consider using the <!-- code({ src: \"path/to/example.ts\" })--> comment as well.\n```\n\n```ts\n// If importable, code block indicating both import functionality and usage.\n```\n\n### CLI\n\n```ts\n// If CLI compatible, code block indicating common usage.\n```\n\n## _Extra Sections (Rename)_\n\n## Security\n\n## API\n\n_Describe exported functions and objects._\n\n- _Describe signatures, return types, callbacks, and events._\n- _Cover types covered where not obvious._\n- _Describe caveats._\n- _If using an external API generator (like go-doc, js-doc, or so on), point to an external API.md file. This can be the only item in the section, if present._\n\n## Maintainers\n\n_List maintainer(s) for a repository, along with one way of contacting them (e.g. GitHub link or email)._\n\n## Thanks\n\n_State anyone or anything that significantly helped with the development of your project. State public contact hyper-links if applicable._\n\n<!-- contributing -->\n\n<!-- license -->\n"
817
931
  },
818
932
  description: "Includes all sections from the Standard Readme specification.",
819
933
  exampleLink: "https://github.com/RichardLitt/standard-readme/blob/main/example-readmes/maximal-readme.md"
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "mdat",
3
- "version": "2.2.0",
3
+ "version": "2.3.0",
4
4
  "description": "CLI tool and TypeScript library implementing the Markdown Autophagic Template (MDAT) system. MDAT lets you use comments as dynamic content templates in Markdown files, making it easy to generate and update readme boilerplate.",
5
5
  "keywords": [
6
6
  "mdat",
@@ -45,12 +45,12 @@
45
45
  "dependencies": {
46
46
  "@clack/prompts": "^1.2.0",
47
47
  "cosmiconfig": "^9.0.1",
48
- "cosmiconfig-typescript-loader": "^6.2.0",
48
+ "cosmiconfig-typescript-loader": "^6.3.0",
49
49
  "deepmerge-ts": "^7.1.5",
50
50
  "globby": "^16.2.0",
51
- "lognow": "^0.6.0",
51
+ "lognow": "^0.6.1",
52
52
  "mdast-util-toc": "^7.1.0",
53
- "metascope": "^0.6.0",
53
+ "metascope": "^0.7.0",
54
54
  "path-type": "^6.0.0",
55
55
  "picocolors": "^1.1.1",
56
56
  "plur": "^6.0.0",
@@ -58,9 +58,9 @@
58
58
  "pretty-ms": "^9.3.0",
59
59
  "remark": "^15.0.1",
60
60
  "remark-gfm": "^4.0.1",
61
- "remark-mdat": "^2.2.0",
61
+ "remark-mdat": "^2.2.1",
62
62
  "to-vfile": "^8.0.0",
63
- "type-fest": "^5.5.0",
63
+ "type-fest": "^5.6.0",
64
64
  "unified-engine": "^11.2.2",
65
65
  "untildify": "^6.0.0",
66
66
  "vfile": "^6.0.3",
@@ -69,7 +69,7 @@
69
69
  },
70
70
  "devDependencies": {
71
71
  "@arethetypeswrong/core": "^0.18.2",
72
- "@kitschpatrol/shared-config": "^7.0.1",
72
+ "@kitschpatrol/shared-config": "^7.4.1",
73
73
  "@types/mdast": "^4.0.4",
74
74
  "@types/node": "~22.17.2",
75
75
  "@types/unist": "^3.0.3",
@@ -77,16 +77,17 @@
77
77
  "@vitest/coverage-v8": "4.1.2",
78
78
  "bumpp": "^11.0.1",
79
79
  "execa": "^9.6.1",
80
- "mdat-plugin-cli-help": "^2.0.2",
80
+ "mdat-plugin-cli-help": "^2.1.2",
81
81
  "mdat-plugin-example": "^2.0.0",
82
82
  "mdat-plugin-tldraw": "^2.0.1",
83
- "nanoid": "^5.1.7",
84
- "prettier": "^3.8.1",
83
+ "nanoid": "^5.1.9",
84
+ "prettier": "^3.8.3",
85
85
  "publint": "^0.3.18",
86
- "tsdown": "^0.21.7",
87
- "typescript": "~5.9.3",
86
+ "shx": "^0.4.0",
87
+ "tsdown": "^0.21.9",
88
+ "typescript": "~6.0.3",
88
89
  "unplugin-raw": "^0.7.0",
89
- "vitest": "^4.1.2"
90
+ "vitest": "^4.1.5"
90
91
  },
91
92
  "peerDependencies": {
92
93
  "prettier": "^3.0.0"
@@ -109,11 +110,11 @@
109
110
  "bench": "vitest bench --run --compare test/benchmarks/baseline.json",
110
111
  "bench:baseline": "vitest bench --run --outputJson test/benchmarks/baseline.json",
111
112
  "build": "tsdown",
112
- "clean": "git rm -f pnpm-lock.yaml ; git clean -fdX",
113
+ "clean": "shx rm -f pnpm-lock.yaml && git clean -fdX -e !.claude/",
113
114
  "coverage": "vitest --coverage --run",
114
115
  "fix": "ksc fix",
115
116
  "lint": "ksc lint",
116
- "release": "bumpp --commit 'Release: %s' && pnpm run build && NPM_AUTH_TOKEN=$(op read 'op://Personal/npm/token') && pnpm publish",
117
+ "release": "bumpp --commit 'Release: %s' && pnpm build && NPM_AUTH_TOKEN=$(op read 'op://Personal/npm/token') && pnpm publish",
117
118
  "test": "vitest run"
118
119
  }
119
120
  }
package/readme.md CHANGED
@@ -572,6 +572,14 @@ See the [Examples section](https://github.com/kitschpatrol/remark-mdat#examples)
572
572
 
573
573
  The project description. Also aliased as `<!-- short-description -->` for [standard-readme](https://github.com/RichardLitt/standard-readme/blob/main/spec.md) compatibility.
574
574
 
575
+ - ##### `<!-- install -->`
576
+
577
+ Ecosystem-aware install instructions derived from project metadata. Emits `pnpm add` / `npm install` for Node packages (plus a `pnpx` / `npx` hint when the project exposes a binary), and falls back to `pip`, `cargo`, `gem`, or `go install` for Python, Rust, Ruby, and Go projects.
578
+
579
+ - ##### `<!-- dependencies -->`
580
+
581
+ Documents platform requirements and peer dependencies. Lists runtime platforms (Node, Python, Rust, Go, Ruby, etc.) with version constraints from `engines` or equivalent metadata, supported operating systems, and peer dependencies with links to npm.
582
+
575
583
  - ##### `<!-- table-of-contents -->`
576
584
 
577
585
  Auto-generated via [mdast-util-toc](https://github.com/syntax-tree/mdast-util-toc). Also aliased as `<!-- toc -->`.
@@ -600,7 +608,7 @@ See the [Examples section](https://github.com/kitschpatrol/remark-mdat#examples)
600
608
 
601
609
  | File | Original | Gzip | Brotli |
602
610
  | ----------- | -------- | ----- | ------ |
603
- | .gitignore | 305 B | 245 B | 216 B |
611
+ | .gitignore | 318 B | 252 B | 237 B |
604
612
  | license.txt | 1 kB | 659 B | 468 B |
605
613
 
606
614
  <!-- /size-table -->
@@ -794,13 +802,17 @@ There's quite a bit of prior art and similar explorations of this problem space:
794
802
 
795
803
  - VitePress' [Markdown file inclusion](https://vitepress.dev/guide/markdown#markdown-file-inclusion)
796
804
 
805
+ - Hiroki Osame's [comment-mark](https://github.com/privatenumber/comment-mark)
806
+
807
+ - Hiroki Osame's [mdeval](https://github.com/privatenumber/mdeval)
808
+
797
809
  ### Implementation notes
798
810
 
799
811
  This project was split from a monorepo containing both `mdat` and `remark-mdat` into separate repos in July 2024.
800
812
 
801
813
  ## Maintainers
802
814
 
803
- [@kitschpatrol](https://github.com/kitschpatrol)
815
+ [kitschpatrol](https://github.com/kitschpatrol)
804
816
 
805
817
  ## Acknowledgments
806
818
 
package/dist/.DS_Store DELETED
Binary file