mdat 2.2.1 → 2.3.1
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 +163 -20
- package/dist/lib/index.d.ts +55 -19
- package/dist/lib/index.js +167 -45
- package/package.json +16 -15
- package/readme.md +20 -4
- package/dist/.DS_Store +0 -0
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.
|
|
45
|
+
var version = "2.3.1";
|
|
46
46
|
|
|
47
47
|
//#endregion
|
|
48
48
|
//#region src/lib/log.ts
|
|
@@ -56,9 +56,11 @@ let log = createLogger({
|
|
|
56
56
|
setLogger(getChildLogger(log, "remark-mdat"));
|
|
57
57
|
setLogger$1(getChildLogger(log, "metascope"));
|
|
58
58
|
/**
|
|
59
|
-
* Set the logger instance for the module.
|
|
60
|
-
*
|
|
61
|
-
*
|
|
59
|
+
* Set the logger instance for the module. Export this for library consumers to
|
|
60
|
+
* inject their own logger.
|
|
61
|
+
*
|
|
62
|
+
* @param logger - Accepts either a LogLayer instance or a Console- or
|
|
63
|
+
* Stream-like log target
|
|
62
64
|
*/
|
|
63
65
|
function setLogger$2(logger) {
|
|
64
66
|
log = injectionHelper(logger);
|
|
@@ -69,9 +71,10 @@ function setLogger$2(logger) {
|
|
|
69
71
|
//#endregion
|
|
70
72
|
//#region src/lib/mdat-json-loader.ts
|
|
71
73
|
/**
|
|
72
|
-
* Lets arbitrary JSON objects (like from package.json) become reasonably good
|
|
73
|
-
* HOWEVER cosmiconfig treats package.json as a special case and
|
|
74
|
-
* So we have to intercept and load
|
|
74
|
+
* Lets arbitrary JSON objects (like from package.json) become reasonably good
|
|
75
|
+
* mdat rule sets HOWEVER cosmiconfig treats package.json as a special case and
|
|
76
|
+
* will always load only specific keys from it So we have to intercept and load
|
|
77
|
+
* them manually in config.ts
|
|
75
78
|
*/
|
|
76
79
|
function mdatJsonLoader(filePath, content) {
|
|
77
80
|
const defaultJsonLoader = defaultLoaders[".json"];
|
|
@@ -144,17 +147,53 @@ const readmeMetadataTemplate = defineTemplate((context) => {
|
|
|
144
147
|
const licenseFileData = helpers.firstOf(licenseFile);
|
|
145
148
|
const ciActionFilePath = helpers.ensureArray(githubActions).find((entry) => entry.data.name.toLowerCase() === "ci")?.source;
|
|
146
149
|
const repositoryUrl = codemeta.codeRepository?.replace(GIT_PREFIX_REGEX, "").replace(GIT_SUFFIX_REGEX, "").replace(TRAILING_SLASH_REGEX, "");
|
|
150
|
+
const bin = (() => {
|
|
151
|
+
if (nodePackage === void 0) return;
|
|
152
|
+
const binField = nodePackage.bin;
|
|
153
|
+
if (binField === void 0) return;
|
|
154
|
+
if (typeof binField === "string") return [nodePackage.name];
|
|
155
|
+
const names = Object.keys(binField);
|
|
156
|
+
return names.length > 0 ? names : void 0;
|
|
157
|
+
})();
|
|
158
|
+
const engines = (() => {
|
|
159
|
+
const raw = nodePackage?.engines;
|
|
160
|
+
if (raw === void 0) return;
|
|
161
|
+
const entries = Object.entries(raw).filter((entry) => entry[1] !== void 0);
|
|
162
|
+
return entries.length > 0 ? Object.fromEntries(entries) : void 0;
|
|
163
|
+
})();
|
|
164
|
+
const peerDependencies = (() => {
|
|
165
|
+
if (nodePackage === void 0) return;
|
|
166
|
+
const peers = nodePackage.peerDependencies;
|
|
167
|
+
if (peers === void 0) return;
|
|
168
|
+
const entries = Object.entries(peers).filter((entry) => entry[1] !== void 0);
|
|
169
|
+
if (entries.length === 0) return;
|
|
170
|
+
const meta = nodePackage.peerDependenciesMeta;
|
|
171
|
+
return entries.map(([name, version]) => ({
|
|
172
|
+
name,
|
|
173
|
+
optional: meta?.[name]?.optional === true,
|
|
174
|
+
version
|
|
175
|
+
}));
|
|
176
|
+
})();
|
|
177
|
+
const firstAuthor = helpers.firstOf(helpers.ensureArray(codemeta.author));
|
|
147
178
|
return {
|
|
148
179
|
author: helpers.firstOf(helpers.mixedStringsToArray(helpers.toBasicNames(codemeta.author))),
|
|
180
|
+
authorUrl: firstAuthor?.url,
|
|
181
|
+
bin,
|
|
149
182
|
ciActionFileName: ciActionFilePath ? path.basename(ciActionFilePath) : void 0,
|
|
150
183
|
description: codemeta.description,
|
|
151
|
-
|
|
184
|
+
engines,
|
|
185
|
+
isPublicNpmPackage: nodePackage?.private !== true && (nodePackage?.name.startsWith("@") && nodePackage.publishConfig?.access === "public" || true),
|
|
152
186
|
issuesUrl: codemeta.issueTracker,
|
|
153
187
|
license: helpers.toBasicLicense(helpers.firstOf(helpers.ensureArray(codemeta.license))),
|
|
154
188
|
licenseFilePath: licenseFileData?.source,
|
|
189
|
+
licenseUrl: licenseFileData?.data.spdxUrl,
|
|
155
190
|
name: codemeta.name,
|
|
191
|
+
operatingSystem: codemeta.operatingSystem,
|
|
192
|
+
peerDependencies,
|
|
156
193
|
projectDirectory: metascope?.data.options.path === void 0 ? void 0 : `file://${metascope.data.options.path}`,
|
|
157
|
-
repositoryUrl
|
|
194
|
+
repositoryUrl,
|
|
195
|
+
runtimePlatform: codemeta.runtimePlatform,
|
|
196
|
+
usesPnpm: helpers.usesPnpm(nodePackageJson)
|
|
158
197
|
};
|
|
159
198
|
});
|
|
160
199
|
let readmeMetadata;
|
|
@@ -180,12 +219,12 @@ var badges_default = { badges: { async content(options) {
|
|
|
180
219
|
npm: z.array(z.string()).optional()
|
|
181
220
|
}).optional().parse(options);
|
|
182
221
|
const metadata = await getReadmeMetadata();
|
|
183
|
-
const { ciActionFileName, license, name, repositoryUrl } = metadata;
|
|
222
|
+
const { ciActionFileName, license, licenseUrl, name, repositoryUrl } = metadata;
|
|
184
223
|
const badges = [];
|
|
185
224
|
if (validOptions?.npm === void 0) {
|
|
186
225
|
if (metadata.isPublicNpmPackage) badges.push(`[](https://npmjs.com/package/${name})`);
|
|
187
226
|
} else for (const name of validOptions.npm) badges.push(`[](https://npmjs.com/package/${name})`);
|
|
188
|
-
if (license !== void 0) badges.push(`[}-yellow.svg)](
|
|
227
|
+
if (license !== void 0 && licenseUrl !== void 0) badges.push(`[}-yellow.svg)](${licenseUrl})`);
|
|
189
228
|
if (ciActionFileName !== void 0 && repositoryUrl !== void 0) badges.push(`[](${repositoryUrl}/actions/workflows/${ciActionFileName})`);
|
|
190
229
|
if (validOptions?.custom !== void 0) for (const [name, { image, link }] of Object.entries(validOptions.custom)) badges.push(`[](${link})`);
|
|
191
230
|
return badges.join("\n");
|
|
@@ -278,7 +317,85 @@ var code_default = { code: { async content(options) {
|
|
|
278
317
|
var contributing_default = { contributing: { async content() {
|
|
279
318
|
const { issuesUrl } = await getReadmeMetadata();
|
|
280
319
|
if (issuesUrl === void 0) throw new Error("Could not find \"bugs.url\" entry in package.json");
|
|
281
|
-
return
|
|
320
|
+
return [
|
|
321
|
+
"## Contributing",
|
|
322
|
+
"",
|
|
323
|
+
`[Issues](${issuesUrl}) are welcome and appreciated.`,
|
|
324
|
+
"",
|
|
325
|
+
"Please open an issue to discuss changes before submitting a pull request. Unsolicited PRs (especially AI-generated ones) are unlikely to be merged.",
|
|
326
|
+
"",
|
|
327
|
+
"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."
|
|
328
|
+
].join("\n");
|
|
329
|
+
} } };
|
|
330
|
+
|
|
331
|
+
//#endregion
|
|
332
|
+
//#region src/lib/readme/rules/dependencies.ts
|
|
333
|
+
const PLATFORM_INFO = {
|
|
334
|
+
bun: {
|
|
335
|
+
display: "Bun",
|
|
336
|
+
url: "https://bun.sh/"
|
|
337
|
+
},
|
|
338
|
+
deno: {
|
|
339
|
+
display: "Deno",
|
|
340
|
+
url: "https://deno.land/"
|
|
341
|
+
},
|
|
342
|
+
go: {
|
|
343
|
+
display: "Go",
|
|
344
|
+
url: "https://go.dev/"
|
|
345
|
+
},
|
|
346
|
+
java: {
|
|
347
|
+
display: "Java",
|
|
348
|
+
url: "https://www.java.com/"
|
|
349
|
+
},
|
|
350
|
+
node: {
|
|
351
|
+
display: "Node.js",
|
|
352
|
+
url: "https://nodejs.org/"
|
|
353
|
+
},
|
|
354
|
+
python: {
|
|
355
|
+
display: "Python",
|
|
356
|
+
url: "https://www.python.org/"
|
|
357
|
+
},
|
|
358
|
+
ruby: {
|
|
359
|
+
display: "Ruby",
|
|
360
|
+
url: "https://www.ruby-lang.org/"
|
|
361
|
+
},
|
|
362
|
+
rust: {
|
|
363
|
+
display: "Rust",
|
|
364
|
+
url: "https://www.rust-lang.org/"
|
|
365
|
+
}
|
|
366
|
+
};
|
|
367
|
+
var dependencies_default = { dependencies: { async content() {
|
|
368
|
+
const { engines, operatingSystem, peerDependencies, runtimePlatform } = await getReadmeMetadata();
|
|
369
|
+
const platformItems = [];
|
|
370
|
+
if (engines !== void 0) for (const [name, version] of Object.entries(engines)) {
|
|
371
|
+
const info = PLATFORM_INFO[name.toLowerCase()];
|
|
372
|
+
const display = info ? `[${info.display}](${info.url})` : name;
|
|
373
|
+
platformItems.push(`- ${display} ${version}`);
|
|
374
|
+
}
|
|
375
|
+
if (runtimePlatform !== void 0) for (const entry of runtimePlatform) {
|
|
376
|
+
const spaceIndex = entry.indexOf(" ");
|
|
377
|
+
const platformKey = spaceIndex > 0 ? entry.slice(0, spaceIndex) : entry;
|
|
378
|
+
const version = spaceIndex > 0 ? entry.slice(spaceIndex + 1) : void 0;
|
|
379
|
+
if (engines?.[platformKey] !== void 0) continue;
|
|
380
|
+
const info = PLATFORM_INFO[platformKey.toLowerCase()];
|
|
381
|
+
const display = info ? `[${info.display}](${info.url})` : platformKey;
|
|
382
|
+
platformItems.push(version ? `- ${display} ${version}` : `- ${display}`);
|
|
383
|
+
}
|
|
384
|
+
if (operatingSystem !== void 0 && operatingSystem.length > 0) platformItems.push(`- Supported platforms: ${operatingSystem.join(", ")}`);
|
|
385
|
+
const peerItems = [];
|
|
386
|
+
if (peerDependencies !== void 0) for (const { name, optional, version } of peerDependencies) {
|
|
387
|
+
const npmUrl = `https://www.npmjs.com/package/${name}`;
|
|
388
|
+
const optionalSuffix = optional ? " _(optional)_" : "";
|
|
389
|
+
peerItems.push(`- [${name}](${npmUrl}) ${version}${optionalSuffix}`);
|
|
390
|
+
}
|
|
391
|
+
const hasPlatform = platformItems.length > 0;
|
|
392
|
+
const hasPeers = peerItems.length > 0;
|
|
393
|
+
if (!hasPlatform && !hasPeers) return "";
|
|
394
|
+
const sections = ["## Dependencies"];
|
|
395
|
+
if (hasPlatform && hasPeers) sections.push("", "### Platform", "", ...platformItems, "", "### Peer Dependencies", "", ...peerItems);
|
|
396
|
+
else if (hasPlatform) sections.push("", ...platformItems);
|
|
397
|
+
else sections.push("", ...peerItems);
|
|
398
|
+
return sections.join("\n");
|
|
282
399
|
} } };
|
|
283
400
|
|
|
284
401
|
//#endregion
|
|
@@ -295,10 +412,10 @@ var description_default = { description: { async content() {
|
|
|
295
412
|
//#endregion
|
|
296
413
|
//#region src/lib/readme/rules/license.ts
|
|
297
414
|
var license_default = { license: { async content() {
|
|
298
|
-
const { author, license, licenseFilePath } = await getReadmeMetadata();
|
|
415
|
+
const { author, authorUrl, license, licenseFilePath } = await getReadmeMetadata();
|
|
299
416
|
if (author === void 0) throw new Error("Could not find author name in project");
|
|
300
417
|
if (license === void 0 || licenseFilePath === void 0) throw new Error("Could not find license for project");
|
|
301
|
-
return `## License\n[${license}](${licenseFilePath}) © ${author}`;
|
|
418
|
+
return `## License\n[${license}](${licenseFilePath}) © ${authorUrl === void 0 ? author : `[${author}](${authorUrl})`}`;
|
|
302
419
|
} } };
|
|
303
420
|
|
|
304
421
|
//#endregion
|
|
@@ -346,12 +463,32 @@ var header_default = { header: {
|
|
|
346
463
|
order: 2
|
|
347
464
|
} };
|
|
348
465
|
|
|
466
|
+
//#endregion
|
|
467
|
+
//#region src/lib/readme/rules/install.ts
|
|
468
|
+
var install_default = { install: { async content() {
|
|
469
|
+
const { bin, engines, isPublicNpmPackage, name, runtimePlatform, usesPnpm } = await getReadmeMetadata();
|
|
470
|
+
if (name === void 0) throw new Error("Could not find project name");
|
|
471
|
+
const lines = ["## Install"];
|
|
472
|
+
if (isPublicNpmPackage || engines?.node !== void 0 || runtimePlatform?.includes("node")) {
|
|
473
|
+
const pmAdd = usesPnpm ? "pnpm add" : "npm install";
|
|
474
|
+
const pmx = usesPnpm ? "pnpx" : "npx";
|
|
475
|
+
lines.push("", "```sh", `${pmAdd} ${name}`, "```");
|
|
476
|
+
if (bin !== void 0 && bin.length > 0) lines.push("", "Or run it directly:", "", "```sh", `${pmx} ${name}`, "```");
|
|
477
|
+
} else if (runtimePlatform?.some((p) => p.startsWith("python"))) lines.push("", "```sh", `pip install ${name}`, "```");
|
|
478
|
+
else if (runtimePlatform?.some((p) => p.startsWith("rust"))) lines.push("", "```sh", `cargo install ${name}`, "```");
|
|
479
|
+
else if (runtimePlatform?.some((p) => p.startsWith("go"))) lines.push("", "```sh", `go install ${name}@latest`, "```");
|
|
480
|
+
else if (runtimePlatform?.some((p) => p.startsWith("ruby"))) lines.push("", "```sh", `gem install ${name}`, "```");
|
|
481
|
+
else throw new Error("Could not determine project ecosystem for install instructions");
|
|
482
|
+
return lines.join("\n");
|
|
483
|
+
} } };
|
|
484
|
+
|
|
349
485
|
//#endregion
|
|
350
486
|
//#region src/lib/readme/rules/utilities/size/size-report.ts
|
|
351
487
|
const brotliCompressAsync = promisify(brotliCompress);
|
|
352
488
|
const gzipCompressAsync = promisify(gzip);
|
|
353
489
|
/**
|
|
354
490
|
* Creates a SizeInfo object with formatted values
|
|
491
|
+
*
|
|
355
492
|
* @param bytes - Size in bytes
|
|
356
493
|
* @param originalSize - Original file size for percentage calculation
|
|
357
494
|
*/
|
|
@@ -366,9 +503,11 @@ function createSizeInfo(bytes, originalSize) {
|
|
|
366
503
|
}
|
|
367
504
|
/**
|
|
368
505
|
* Analyzes a file's size and its compressed sizes using Brotli and Gzip
|
|
506
|
+
*
|
|
369
507
|
* @param filePath - Path to the file to analyze
|
|
508
|
+
*
|
|
370
509
|
* @returns Promise containing detailed size report
|
|
371
|
-
* @throws {Error}
|
|
510
|
+
* @throws {Error} If file cannot be read or compressed
|
|
372
511
|
*/
|
|
373
512
|
async function createSizeReport(filePath) {
|
|
374
513
|
try {
|
|
@@ -504,9 +643,11 @@ var rules_default = {
|
|
|
504
643
|
...banner_default,
|
|
505
644
|
...code_default,
|
|
506
645
|
...contributing_default,
|
|
646
|
+
...dependencies_default,
|
|
507
647
|
...description_default,
|
|
508
648
|
...footer_default,
|
|
509
649
|
...header_default,
|
|
650
|
+
...install_default,
|
|
510
651
|
...license_default,
|
|
511
652
|
...short_description_default,
|
|
512
653
|
...size_default,
|
|
@@ -532,9 +673,9 @@ function getAdditionalConfigExplorer() {
|
|
|
532
673
|
return _additionalConfigExplorer;
|
|
533
674
|
}
|
|
534
675
|
/**
|
|
535
|
-
* Load and validate mdat configuration.
|
|
536
|
-
*
|
|
537
|
-
*
|
|
676
|
+
* Load and validate mdat configuration. Uses cosmiconfig to search in the usual
|
|
677
|
+
* places. Merge precedence: Base Defaults < Defaults < Searched Config <
|
|
678
|
+
* Additional Config
|
|
538
679
|
*/
|
|
539
680
|
async function loadConfig(options) {
|
|
540
681
|
const { additionalConfig, defaults = rules_default, searchFrom } = options ?? {};
|
|
@@ -590,8 +731,8 @@ function validateConfig(value) {
|
|
|
590
731
|
let cachedPrettier;
|
|
591
732
|
const configCache = /* @__PURE__ */ new Map();
|
|
592
733
|
/**
|
|
593
|
-
* Format a markdown string with Prettier, using config discovered from the file
|
|
594
|
-
* Requires `prettier` to be installed as a peer dependency.
|
|
734
|
+
* Format a markdown string with Prettier, using config discovered from the file
|
|
735
|
+
* path. Requires `prettier` to be installed as a peer dependency.
|
|
595
736
|
*/
|
|
596
737
|
async function formatWithPrettier(content, filePath) {
|
|
597
738
|
if (cachedPrettier === void 0) try {
|
|
@@ -822,6 +963,7 @@ var templates_default = {
|
|
|
822
963
|
//#region src/lib/readme/create.ts
|
|
823
964
|
/**
|
|
824
965
|
* Creates a new readme file interactively.
|
|
966
|
+
*
|
|
825
967
|
* @returns Path to the created readme file.
|
|
826
968
|
*/
|
|
827
969
|
async function createReadmeInteractive() {
|
|
@@ -862,6 +1004,7 @@ async function createReadmeInteractive() {
|
|
|
862
1004
|
}
|
|
863
1005
|
/**
|
|
864
1006
|
* Creates a new readme file with the given options.
|
|
1007
|
+
*
|
|
865
1008
|
* @returns Path to the created readme file.
|
|
866
1009
|
*/
|
|
867
1010
|
async function createReadme(options) {
|
package/dist/lib/index.d.ts
CHANGED
|
@@ -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
|
-
*
|
|
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
|
-
*
|
|
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
|
-
*
|
|
21
|
-
*
|
|
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
|
-
*
|
|
29
|
-
*
|
|
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
|
|
34
|
-
* Defaults to the built-in readme rules. Pass `{}` to
|
|
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
|
/**
|
|
@@ -56,11 +60,13 @@ type MdatReadmeCreateOptions = {
|
|
|
56
60
|
};
|
|
57
61
|
/**
|
|
58
62
|
* Creates a new readme file interactively.
|
|
63
|
+
*
|
|
59
64
|
* @returns Path to the created readme file.
|
|
60
65
|
*/
|
|
61
66
|
declare function createReadmeInteractive(): Promise<string>;
|
|
62
67
|
/**
|
|
63
68
|
* Creates a new readme file with the given options.
|
|
69
|
+
*
|
|
64
70
|
* @returns Path to the created readme file.
|
|
65
71
|
*/
|
|
66
72
|
declare function createReadme(options?: Partial<MdatReadmeCreateOptions>): Promise<string>;
|
|
@@ -148,15 +154,29 @@ declare function checkString(markdown: string, config?: ConfigToLoad, options?:
|
|
|
148
154
|
declare function getContextMetadata(): Promise<MetadataContext>;
|
|
149
155
|
declare const readmeMetadataTemplate: _$metascope.Template<{
|
|
150
156
|
author: string | undefined;
|
|
157
|
+
authorUrl: string | undefined;
|
|
158
|
+
bin: string[] | undefined;
|
|
151
159
|
ciActionFileName: string | undefined;
|
|
152
160
|
description: string | undefined;
|
|
161
|
+
engines: {
|
|
162
|
+
[k: string]: string;
|
|
163
|
+
} | undefined;
|
|
153
164
|
isPublicNpmPackage: boolean;
|
|
154
165
|
issuesUrl: string | undefined;
|
|
155
166
|
license: string | undefined;
|
|
156
167
|
licenseFilePath: string | undefined;
|
|
168
|
+
licenseUrl: string | undefined;
|
|
157
169
|
name: string | undefined;
|
|
170
|
+
operatingSystem: string[] | undefined;
|
|
171
|
+
peerDependencies: {
|
|
172
|
+
name: string;
|
|
173
|
+
optional: boolean;
|
|
174
|
+
version: string;
|
|
175
|
+
}[] | undefined;
|
|
158
176
|
projectDirectory: string | undefined;
|
|
159
177
|
repositoryUrl: string | undefined;
|
|
178
|
+
runtimePlatform: string[] | undefined;
|
|
179
|
+
usesPnpm: boolean;
|
|
160
180
|
}>;
|
|
161
181
|
type ReadmeMetadata = ReturnType<typeof readmeMetadataTemplate>;
|
|
162
182
|
/**
|
|
@@ -166,15 +186,29 @@ type ReadmeMetadata = ReturnType<typeof readmeMetadataTemplate>;
|
|
|
166
186
|
*/
|
|
167
187
|
declare function getReadmeMetadata(): Promise<{
|
|
168
188
|
author: string | undefined;
|
|
189
|
+
authorUrl: string | undefined;
|
|
190
|
+
bin: string[] | undefined;
|
|
169
191
|
ciActionFileName: string | undefined;
|
|
170
192
|
description: string | undefined;
|
|
193
|
+
engines: {
|
|
194
|
+
[k: string]: string;
|
|
195
|
+
} | undefined;
|
|
171
196
|
isPublicNpmPackage: boolean;
|
|
172
197
|
issuesUrl: string | undefined;
|
|
173
198
|
license: string | undefined;
|
|
174
199
|
licenseFilePath: string | undefined;
|
|
200
|
+
licenseUrl: string | undefined;
|
|
175
201
|
name: string | undefined;
|
|
202
|
+
operatingSystem: string[] | undefined;
|
|
203
|
+
peerDependencies: {
|
|
204
|
+
name: string;
|
|
205
|
+
optional: boolean;
|
|
206
|
+
version: string;
|
|
207
|
+
}[] | undefined;
|
|
176
208
|
projectDirectory: string | undefined;
|
|
177
209
|
repositoryUrl: string | undefined;
|
|
210
|
+
runtimePlatform: string[] | undefined;
|
|
211
|
+
usesPnpm: boolean;
|
|
178
212
|
}>;
|
|
179
213
|
/**
|
|
180
214
|
* Reset all cached metadata. Call between tests or when the underlying project
|
|
@@ -184,10 +218,12 @@ declare function resetMetadataCaches(): void;
|
|
|
184
218
|
//#endregion
|
|
185
219
|
//#region src/lib/log.d.ts
|
|
186
220
|
/**
|
|
187
|
-
* Set the logger instance for the module.
|
|
188
|
-
*
|
|
189
|
-
*
|
|
221
|
+
* Set the logger instance for the module. Export this for library consumers to
|
|
222
|
+
* inject their own logger.
|
|
223
|
+
*
|
|
224
|
+
* @param logger - Accepts either a LogLayer instance or a Console- or
|
|
225
|
+
* Stream-like log target
|
|
190
226
|
*/
|
|
191
|
-
declare function setLogger(logger?: ILogBasic | ILogLayer): void;
|
|
227
|
+
declare function setLogger(logger?: ILogBasic | ILogLayer<unknown>): void;
|
|
192
228
|
//#endregion
|
|
193
229
|
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
|
@@ -45,9 +45,11 @@ let log = createLogger({
|
|
|
45
45
|
setLogger$1(getChildLogger(log, "remark-mdat"));
|
|
46
46
|
setLogger$2(getChildLogger(log, "metascope"));
|
|
47
47
|
/**
|
|
48
|
-
* Set the logger instance for the module.
|
|
49
|
-
*
|
|
50
|
-
*
|
|
48
|
+
* Set the logger instance for the module. Export this for library consumers to
|
|
49
|
+
* inject their own logger.
|
|
50
|
+
*
|
|
51
|
+
* @param logger - Accepts either a LogLayer instance or a Console- or
|
|
52
|
+
* Stream-like log target
|
|
51
53
|
*/
|
|
52
54
|
function setLogger(logger) {
|
|
53
55
|
log = injectionHelper(logger);
|
|
@@ -57,9 +59,10 @@ function setLogger(logger) {
|
|
|
57
59
|
//#endregion
|
|
58
60
|
//#region src/lib/mdat-json-loader.ts
|
|
59
61
|
/**
|
|
60
|
-
* Lets arbitrary JSON objects (like from package.json) become reasonably good
|
|
61
|
-
* HOWEVER cosmiconfig treats package.json as a special case and
|
|
62
|
-
* So we have to intercept and load
|
|
62
|
+
* Lets arbitrary JSON objects (like from package.json) become reasonably good
|
|
63
|
+
* mdat rule sets HOWEVER cosmiconfig treats package.json as a special case and
|
|
64
|
+
* will always load only specific keys from it So we have to intercept and load
|
|
65
|
+
* them manually in config.ts
|
|
63
66
|
*/
|
|
64
67
|
function mdatJsonLoader(filePath, content) {
|
|
65
68
|
const defaultJsonLoader = defaultLoaders[".json"];
|
|
@@ -140,17 +143,53 @@ const readmeMetadataTemplate = defineTemplate((context) => {
|
|
|
140
143
|
const licenseFileData = helpers.firstOf(licenseFile);
|
|
141
144
|
const ciActionFilePath = helpers.ensureArray(githubActions).find((entry) => entry.data.name.toLowerCase() === "ci")?.source;
|
|
142
145
|
const repositoryUrl = codemeta.codeRepository?.replace(GIT_PREFIX_REGEX, "").replace(GIT_SUFFIX_REGEX, "").replace(TRAILING_SLASH_REGEX, "");
|
|
146
|
+
const bin = (() => {
|
|
147
|
+
if (nodePackage === void 0) return;
|
|
148
|
+
const binField = nodePackage.bin;
|
|
149
|
+
if (binField === void 0) return;
|
|
150
|
+
if (typeof binField === "string") return [nodePackage.name];
|
|
151
|
+
const names = Object.keys(binField);
|
|
152
|
+
return names.length > 0 ? names : void 0;
|
|
153
|
+
})();
|
|
154
|
+
const engines = (() => {
|
|
155
|
+
const raw = nodePackage?.engines;
|
|
156
|
+
if (raw === void 0) return;
|
|
157
|
+
const entries = Object.entries(raw).filter((entry) => entry[1] !== void 0);
|
|
158
|
+
return entries.length > 0 ? Object.fromEntries(entries) : void 0;
|
|
159
|
+
})();
|
|
160
|
+
const peerDependencies = (() => {
|
|
161
|
+
if (nodePackage === void 0) return;
|
|
162
|
+
const peers = nodePackage.peerDependencies;
|
|
163
|
+
if (peers === void 0) return;
|
|
164
|
+
const entries = Object.entries(peers).filter((entry) => entry[1] !== void 0);
|
|
165
|
+
if (entries.length === 0) return;
|
|
166
|
+
const meta = nodePackage.peerDependenciesMeta;
|
|
167
|
+
return entries.map(([name, version]) => ({
|
|
168
|
+
name,
|
|
169
|
+
optional: meta?.[name]?.optional === true,
|
|
170
|
+
version
|
|
171
|
+
}));
|
|
172
|
+
})();
|
|
173
|
+
const firstAuthor = helpers.firstOf(helpers.ensureArray(codemeta.author));
|
|
143
174
|
return {
|
|
144
175
|
author: helpers.firstOf(helpers.mixedStringsToArray(helpers.toBasicNames(codemeta.author))),
|
|
176
|
+
authorUrl: firstAuthor?.url,
|
|
177
|
+
bin,
|
|
145
178
|
ciActionFileName: ciActionFilePath ? path.basename(ciActionFilePath) : void 0,
|
|
146
179
|
description: codemeta.description,
|
|
147
|
-
|
|
180
|
+
engines,
|
|
181
|
+
isPublicNpmPackage: nodePackage?.private !== true && (nodePackage?.name.startsWith("@") && nodePackage.publishConfig?.access === "public" || true),
|
|
148
182
|
issuesUrl: codemeta.issueTracker,
|
|
149
183
|
license: helpers.toBasicLicense(helpers.firstOf(helpers.ensureArray(codemeta.license))),
|
|
150
184
|
licenseFilePath: licenseFileData?.source,
|
|
185
|
+
licenseUrl: licenseFileData?.data.spdxUrl,
|
|
151
186
|
name: codemeta.name,
|
|
187
|
+
operatingSystem: codemeta.operatingSystem,
|
|
188
|
+
peerDependencies,
|
|
152
189
|
projectDirectory: metascope?.data.options.path === void 0 ? void 0 : `file://${metascope.data.options.path}`,
|
|
153
|
-
repositoryUrl
|
|
190
|
+
repositoryUrl,
|
|
191
|
+
runtimePlatform: codemeta.runtimePlatform,
|
|
192
|
+
usesPnpm: helpers.usesPnpm(nodePackageJson)
|
|
154
193
|
};
|
|
155
194
|
});
|
|
156
195
|
let readmeMetadata;
|
|
@@ -192,12 +231,12 @@ var badges_default = { badges: { async content(options) {
|
|
|
192
231
|
npm: z.array(z.string()).optional()
|
|
193
232
|
}).optional().parse(options);
|
|
194
233
|
const metadata = await getReadmeMetadata();
|
|
195
|
-
const { ciActionFileName, license, name, repositoryUrl } = metadata;
|
|
234
|
+
const { ciActionFileName, license, licenseUrl, name, repositoryUrl } = metadata;
|
|
196
235
|
const badges = [];
|
|
197
236
|
if (validOptions?.npm === void 0) {
|
|
198
237
|
if (metadata.isPublicNpmPackage) badges.push(`[](https://npmjs.com/package/${name})`);
|
|
199
238
|
} else for (const name of validOptions.npm) badges.push(`[](https://npmjs.com/package/${name})`);
|
|
200
|
-
if (license !== void 0) badges.push(`[}-yellow.svg)](
|
|
239
|
+
if (license !== void 0 && licenseUrl !== void 0) badges.push(`[}-yellow.svg)](${licenseUrl})`);
|
|
201
240
|
if (ciActionFileName !== void 0 && repositoryUrl !== void 0) badges.push(`[](${repositoryUrl}/actions/workflows/${ciActionFileName})`);
|
|
202
241
|
if (validOptions?.custom !== void 0) for (const [name, { image, link }] of Object.entries(validOptions.custom)) badges.push(`[](${link})`);
|
|
203
242
|
return badges.join("\n");
|
|
@@ -287,7 +326,84 @@ var code_default = { code: { async content(options) {
|
|
|
287
326
|
var contributing_default = { contributing: { async content() {
|
|
288
327
|
const { issuesUrl } = await getReadmeMetadata();
|
|
289
328
|
if (issuesUrl === void 0) throw new Error("Could not find \"bugs.url\" entry in package.json");
|
|
290
|
-
return
|
|
329
|
+
return [
|
|
330
|
+
"## Contributing",
|
|
331
|
+
"",
|
|
332
|
+
`[Issues](${issuesUrl}) are welcome and appreciated.`,
|
|
333
|
+
"",
|
|
334
|
+
"Please open an issue to discuss changes before submitting a pull request. Unsolicited PRs (especially AI-generated ones) are unlikely to be merged.",
|
|
335
|
+
"",
|
|
336
|
+
"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."
|
|
337
|
+
].join("\n");
|
|
338
|
+
} } };
|
|
339
|
+
//#endregion
|
|
340
|
+
//#region src/lib/readme/rules/dependencies.ts
|
|
341
|
+
const PLATFORM_INFO = {
|
|
342
|
+
bun: {
|
|
343
|
+
display: "Bun",
|
|
344
|
+
url: "https://bun.sh/"
|
|
345
|
+
},
|
|
346
|
+
deno: {
|
|
347
|
+
display: "Deno",
|
|
348
|
+
url: "https://deno.land/"
|
|
349
|
+
},
|
|
350
|
+
go: {
|
|
351
|
+
display: "Go",
|
|
352
|
+
url: "https://go.dev/"
|
|
353
|
+
},
|
|
354
|
+
java: {
|
|
355
|
+
display: "Java",
|
|
356
|
+
url: "https://www.java.com/"
|
|
357
|
+
},
|
|
358
|
+
node: {
|
|
359
|
+
display: "Node.js",
|
|
360
|
+
url: "https://nodejs.org/"
|
|
361
|
+
},
|
|
362
|
+
python: {
|
|
363
|
+
display: "Python",
|
|
364
|
+
url: "https://www.python.org/"
|
|
365
|
+
},
|
|
366
|
+
ruby: {
|
|
367
|
+
display: "Ruby",
|
|
368
|
+
url: "https://www.ruby-lang.org/"
|
|
369
|
+
},
|
|
370
|
+
rust: {
|
|
371
|
+
display: "Rust",
|
|
372
|
+
url: "https://www.rust-lang.org/"
|
|
373
|
+
}
|
|
374
|
+
};
|
|
375
|
+
var dependencies_default = { dependencies: { async content() {
|
|
376
|
+
const { engines, operatingSystem, peerDependencies, runtimePlatform } = await getReadmeMetadata();
|
|
377
|
+
const platformItems = [];
|
|
378
|
+
if (engines !== void 0) for (const [name, version] of Object.entries(engines)) {
|
|
379
|
+
const info = PLATFORM_INFO[name.toLowerCase()];
|
|
380
|
+
const display = info ? `[${info.display}](${info.url})` : name;
|
|
381
|
+
platformItems.push(`- ${display} ${version}`);
|
|
382
|
+
}
|
|
383
|
+
if (runtimePlatform !== void 0) for (const entry of runtimePlatform) {
|
|
384
|
+
const spaceIndex = entry.indexOf(" ");
|
|
385
|
+
const platformKey = spaceIndex > 0 ? entry.slice(0, spaceIndex) : entry;
|
|
386
|
+
const version = spaceIndex > 0 ? entry.slice(spaceIndex + 1) : void 0;
|
|
387
|
+
if (engines?.[platformKey] !== void 0) continue;
|
|
388
|
+
const info = PLATFORM_INFO[platformKey.toLowerCase()];
|
|
389
|
+
const display = info ? `[${info.display}](${info.url})` : platformKey;
|
|
390
|
+
platformItems.push(version ? `- ${display} ${version}` : `- ${display}`);
|
|
391
|
+
}
|
|
392
|
+
if (operatingSystem !== void 0 && operatingSystem.length > 0) platformItems.push(`- Supported platforms: ${operatingSystem.join(", ")}`);
|
|
393
|
+
const peerItems = [];
|
|
394
|
+
if (peerDependencies !== void 0) for (const { name, optional, version } of peerDependencies) {
|
|
395
|
+
const npmUrl = `https://www.npmjs.com/package/${name}`;
|
|
396
|
+
const optionalSuffix = optional ? " _(optional)_" : "";
|
|
397
|
+
peerItems.push(`- [${name}](${npmUrl}) ${version}${optionalSuffix}`);
|
|
398
|
+
}
|
|
399
|
+
const hasPlatform = platformItems.length > 0;
|
|
400
|
+
const hasPeers = peerItems.length > 0;
|
|
401
|
+
if (!hasPlatform && !hasPeers) return "";
|
|
402
|
+
const sections = ["## Dependencies"];
|
|
403
|
+
if (hasPlatform && hasPeers) sections.push("", "### Platform", "", ...platformItems, "", "### Peer Dependencies", "", ...peerItems);
|
|
404
|
+
else if (hasPlatform) sections.push("", ...platformItems);
|
|
405
|
+
else sections.push("", ...peerItems);
|
|
406
|
+
return sections.join("\n");
|
|
291
407
|
} } };
|
|
292
408
|
//#endregion
|
|
293
409
|
//#region src/lib/readme/rules/description.ts
|
|
@@ -302,10 +418,10 @@ var description_default = { description: { async content() {
|
|
|
302
418
|
//#endregion
|
|
303
419
|
//#region src/lib/readme/rules/license.ts
|
|
304
420
|
var license_default = { license: { async content() {
|
|
305
|
-
const { author, license, licenseFilePath } = await getReadmeMetadata();
|
|
421
|
+
const { author, authorUrl, license, licenseFilePath } = await getReadmeMetadata();
|
|
306
422
|
if (author === void 0) throw new Error("Could not find author name in project");
|
|
307
423
|
if (license === void 0 || licenseFilePath === void 0) throw new Error("Could not find license for project");
|
|
308
|
-
return `## License\n[${license}](${licenseFilePath}) © ${author}`;
|
|
424
|
+
return `## License\n[${license}](${licenseFilePath}) © ${authorUrl === void 0 ? author : `[${author}](${authorUrl})`}`;
|
|
309
425
|
} } };
|
|
310
426
|
//#endregion
|
|
311
427
|
//#region src/lib/readme/rules/footer.ts
|
|
@@ -349,11 +465,30 @@ var header_default = { header: {
|
|
|
349
465
|
order: 2
|
|
350
466
|
} };
|
|
351
467
|
//#endregion
|
|
468
|
+
//#region src/lib/readme/rules/install.ts
|
|
469
|
+
var install_default = { install: { async content() {
|
|
470
|
+
const { bin, engines, isPublicNpmPackage, name, runtimePlatform, usesPnpm } = await getReadmeMetadata();
|
|
471
|
+
if (name === void 0) throw new Error("Could not find project name");
|
|
472
|
+
const lines = ["## Install"];
|
|
473
|
+
if (isPublicNpmPackage || engines?.node !== void 0 || runtimePlatform?.includes("node")) {
|
|
474
|
+
const pmAdd = usesPnpm ? "pnpm add" : "npm install";
|
|
475
|
+
const pmx = usesPnpm ? "pnpx" : "npx";
|
|
476
|
+
lines.push("", "```sh", `${pmAdd} ${name}`, "```");
|
|
477
|
+
if (bin !== void 0 && bin.length > 0) lines.push("", "Or run it directly:", "", "```sh", `${pmx} ${name}`, "```");
|
|
478
|
+
} else if (runtimePlatform?.some((p) => p.startsWith("python"))) lines.push("", "```sh", `pip install ${name}`, "```");
|
|
479
|
+
else if (runtimePlatform?.some((p) => p.startsWith("rust"))) lines.push("", "```sh", `cargo install ${name}`, "```");
|
|
480
|
+
else if (runtimePlatform?.some((p) => p.startsWith("go"))) lines.push("", "```sh", `go install ${name}@latest`, "```");
|
|
481
|
+
else if (runtimePlatform?.some((p) => p.startsWith("ruby"))) lines.push("", "```sh", `gem install ${name}`, "```");
|
|
482
|
+
else throw new Error("Could not determine project ecosystem for install instructions");
|
|
483
|
+
return lines.join("\n");
|
|
484
|
+
} } };
|
|
485
|
+
//#endregion
|
|
352
486
|
//#region src/lib/readme/rules/utilities/size/size-report.ts
|
|
353
487
|
const brotliCompressAsync = promisify(brotliCompress);
|
|
354
488
|
const gzipCompressAsync = promisify(gzip);
|
|
355
489
|
/**
|
|
356
490
|
* Creates a SizeInfo object with formatted values
|
|
491
|
+
*
|
|
357
492
|
* @param bytes - Size in bytes
|
|
358
493
|
* @param originalSize - Original file size for percentage calculation
|
|
359
494
|
*/
|
|
@@ -368,9 +503,11 @@ function createSizeInfo(bytes, originalSize) {
|
|
|
368
503
|
}
|
|
369
504
|
/**
|
|
370
505
|
* Analyzes a file's size and its compressed sizes using Brotli and Gzip
|
|
506
|
+
*
|
|
371
507
|
* @param filePath - Path to the file to analyze
|
|
508
|
+
*
|
|
372
509
|
* @returns Promise containing detailed size report
|
|
373
|
-
* @throws {Error}
|
|
510
|
+
* @throws {Error} If file cannot be read or compressed
|
|
374
511
|
*/
|
|
375
512
|
async function createSizeReport(filePath) {
|
|
376
513
|
try {
|
|
@@ -501,9 +638,11 @@ var rules_default = {
|
|
|
501
638
|
...banner_default,
|
|
502
639
|
...code_default,
|
|
503
640
|
...contributing_default,
|
|
641
|
+
...dependencies_default,
|
|
504
642
|
...description_default,
|
|
505
643
|
...footer_default,
|
|
506
644
|
...header_default,
|
|
645
|
+
...install_default,
|
|
507
646
|
...license_default,
|
|
508
647
|
...short_description_default,
|
|
509
648
|
...size_default,
|
|
@@ -528,9 +667,9 @@ function getAdditionalConfigExplorer() {
|
|
|
528
667
|
return _additionalConfigExplorer;
|
|
529
668
|
}
|
|
530
669
|
/**
|
|
531
|
-
* Load and validate mdat configuration.
|
|
532
|
-
*
|
|
533
|
-
*
|
|
670
|
+
* Load and validate mdat configuration. Uses cosmiconfig to search in the usual
|
|
671
|
+
* places. Merge precedence: Base Defaults < Defaults < Searched Config <
|
|
672
|
+
* Additional Config
|
|
534
673
|
*/
|
|
535
674
|
async function loadConfig(options) {
|
|
536
675
|
const { additionalConfig, defaults = rules_default, searchFrom } = options ?? {};
|
|
@@ -581,8 +720,7 @@ function validateConfig(value) {
|
|
|
581
720
|
log.warn(`Config has the wrong shape. Ignoring and using default configuration:\n${JSON.stringify(value, void 0, 2)}`);
|
|
582
721
|
}
|
|
583
722
|
/**
|
|
584
|
-
* Convenience function for merging configs.
|
|
585
|
-
* Rightmost config takes precedence.
|
|
723
|
+
* Convenience function for merging configs. Rightmost config takes precedence.
|
|
586
724
|
*/
|
|
587
725
|
function mergeConfig(a, b) {
|
|
588
726
|
return deepMergeDefined(a, b);
|
|
@@ -598,8 +736,8 @@ function defineConfig(config) {
|
|
|
598
736
|
let cachedPrettier;
|
|
599
737
|
const configCache = /* @__PURE__ */ new Map();
|
|
600
738
|
/**
|
|
601
|
-
* Format a markdown string with Prettier, using config discovered from the file
|
|
602
|
-
* Requires `prettier` to be installed as a peer dependency.
|
|
739
|
+
* Format a markdown string with Prettier, using config discovered from the file
|
|
740
|
+
* path. Requires `prettier` to be installed as a peer dependency.
|
|
603
741
|
*/
|
|
604
742
|
async function formatWithPrettier(content, filePath) {
|
|
605
743
|
if (cachedPrettier === void 0) try {
|
|
@@ -775,46 +913,28 @@ function getStripProcessor(_config, ambientRemarkConfig) {
|
|
|
775
913
|
});
|
|
776
914
|
}
|
|
777
915
|
//#endregion
|
|
778
|
-
//#region src/lib/readme/templates/mdat-readme-compound.md?raw
|
|
779
|
-
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";
|
|
780
|
-
//#endregion
|
|
781
|
-
//#region src/lib/readme/templates/mdat-readme.md?raw
|
|
782
|
-
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";
|
|
783
|
-
//#endregion
|
|
784
|
-
//#region src/lib/readme/templates/standard-readme-basic-compound.md?raw
|
|
785
|
-
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";
|
|
786
|
-
//#endregion
|
|
787
|
-
//#region src/lib/readme/templates/standard-readme-basic.md?raw
|
|
788
|
-
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";
|
|
789
|
-
//#endregion
|
|
790
|
-
//#region src/lib/readme/templates/standard-readme-full-compound.md?raw
|
|
791
|
-
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";
|
|
792
|
-
//#endregion
|
|
793
|
-
//#region src/lib/readme/templates/standard-readme-full.md?raw
|
|
794
|
-
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";
|
|
795
|
-
//#endregion
|
|
796
916
|
//#region src/lib/readme/templates/index.ts
|
|
797
917
|
var templates_default = {
|
|
798
918
|
"MDAT Readme": {
|
|
799
919
|
content: {
|
|
800
|
-
compound:
|
|
801
|
-
explicit:
|
|
920
|
+
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",
|
|
921
|
+
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"
|
|
802
922
|
},
|
|
803
923
|
description: "The house style. An expansive starting point. Prune to your context and taste.",
|
|
804
924
|
exampleLink: "https://github.com/kitschpatrol/mdat/blob/main/readme.md"
|
|
805
925
|
},
|
|
806
926
|
"Standard Readme Basic": {
|
|
807
927
|
content: {
|
|
808
|
-
compound:
|
|
809
|
-
explicit:
|
|
928
|
+
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",
|
|
929
|
+
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"
|
|
810
930
|
},
|
|
811
931
|
description: "Includes only the \"required\" sections from the Standard Readme specification.",
|
|
812
932
|
exampleLink: "https://github.com/RichardLitt/standard-readme/blob/main/example-readmes/minimal-readme.md"
|
|
813
933
|
},
|
|
814
934
|
"Standard Readme Full": {
|
|
815
935
|
content: {
|
|
816
|
-
compound:
|
|
817
|
-
explicit:
|
|
936
|
+
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",
|
|
937
|
+
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"
|
|
818
938
|
},
|
|
819
939
|
description: "Includes all sections from the Standard Readme specification.",
|
|
820
940
|
exampleLink: "https://github.com/RichardLitt/standard-readme/blob/main/example-readmes/maximal-readme.md"
|
|
@@ -824,6 +944,7 @@ var templates_default = {
|
|
|
824
944
|
//#region src/lib/readme/create.ts
|
|
825
945
|
/**
|
|
826
946
|
* Creates a new readme file interactively.
|
|
947
|
+
*
|
|
827
948
|
* @returns Path to the created readme file.
|
|
828
949
|
*/
|
|
829
950
|
async function createReadmeInteractive() {
|
|
@@ -864,6 +985,7 @@ async function createReadmeInteractive() {
|
|
|
864
985
|
}
|
|
865
986
|
/**
|
|
866
987
|
* Creates a new readme file with the given options.
|
|
988
|
+
*
|
|
867
989
|
* @returns Path to the created readme file.
|
|
868
990
|
*/
|
|
869
991
|
async function createReadme(options) {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "mdat",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.3.1",
|
|
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.
|
|
48
|
+
"cosmiconfig-typescript-loader": "^6.3.0",
|
|
49
49
|
"deepmerge-ts": "^7.1.5",
|
|
50
50
|
"globby": "^16.2.0",
|
|
51
51
|
"lognow": "^0.6.1",
|
|
52
52
|
"mdast-util-toc": "^7.1.0",
|
|
53
|
-
"metascope": "^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.
|
|
61
|
+
"remark-mdat": "^2.2.1",
|
|
62
62
|
"to-vfile": "^8.0.0",
|
|
63
|
-
"type-fest": "^5.
|
|
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.
|
|
72
|
+
"@kitschpatrol/shared-config": "^7.5.2",
|
|
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": "^
|
|
80
|
+
"mdat-plugin-cli-help": "^3.0.0",
|
|
81
81
|
"mdat-plugin-example": "^2.0.0",
|
|
82
|
-
"mdat-plugin-tldraw": "^2.0.
|
|
83
|
-
"nanoid": "^5.1.
|
|
84
|
-
"prettier": "^3.8.
|
|
82
|
+
"mdat-plugin-tldraw": "^2.0.2",
|
|
83
|
+
"nanoid": "^5.1.9",
|
|
84
|
+
"prettier": "^3.8.3",
|
|
85
85
|
"publint": "^0.3.18",
|
|
86
|
-
"
|
|
87
|
-
"
|
|
86
|
+
"shx": "^0.4.0",
|
|
87
|
+
"tsdown": "^0.21.10",
|
|
88
|
+
"typescript": "~6.0.3",
|
|
88
89
|
"unplugin-raw": "^0.7.0",
|
|
89
|
-
"vitest": "^4.1.
|
|
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": "
|
|
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
|
|
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 |
|
|
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
|
-
[
|
|
815
|
+
[kitschpatrol](https://github.com/kitschpatrol)
|
|
804
816
|
|
|
805
817
|
## Acknowledgments
|
|
806
818
|
|
|
@@ -812,10 +824,14 @@ This project was split from a monorepo containing both `mdat` and `remark-mdat`
|
|
|
812
824
|
|
|
813
825
|
## Contributing
|
|
814
826
|
|
|
815
|
-
[Issues](https://github.com/kitschpatrol/mdat/issues)
|
|
827
|
+
[Issues](https://github.com/kitschpatrol/mdat/issues) are welcome and appreciated.
|
|
828
|
+
|
|
829
|
+
Please open an issue to discuss changes before submitting a pull request. Unsolicited PRs (especially AI-generated ones) are unlikely to be merged.
|
|
830
|
+
|
|
831
|
+
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.
|
|
816
832
|
|
|
817
833
|
## License
|
|
818
834
|
|
|
819
|
-
[MIT](license.txt) © Eric Mika
|
|
835
|
+
[MIT](license.txt) © [Eric Mika](https://ericmika.com)
|
|
820
836
|
|
|
821
837
|
<!-- /footer -->
|
package/dist/.DS_Store
DELETED
|
Binary file
|