mdat 3.0.0 → 3.2.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 +121 -29
- package/dist/lib/index.d.ts +22 -0
- package/dist/lib/index.js +102 -19
- package/package.json +24 -24
- package/readme.md +14 -9
package/dist/bin/cli.js
CHANGED
|
@@ -29,7 +29,7 @@ import { confirm, group, intro, note, outro, select } from "@clack/prompts";
|
|
|
29
29
|
|
|
30
30
|
//#region package.json
|
|
31
31
|
var name = "mdat";
|
|
32
|
-
var version = "3.
|
|
32
|
+
var version = "3.2.0";
|
|
33
33
|
|
|
34
34
|
//#endregion
|
|
35
35
|
//#region src/lib/deep-merge-defined.ts
|
|
@@ -41,7 +41,8 @@ function stripUndefinedDeep(object) {
|
|
|
41
41
|
}, {});
|
|
42
42
|
}
|
|
43
43
|
function deepMergeDefined(...objects) {
|
|
44
|
-
|
|
44
|
+
const stripped = objects.map((v, i) => i === 0 ? v : stripUndefinedDeep(v));
|
|
45
|
+
return deepmerge(...stripped);
|
|
45
46
|
}
|
|
46
47
|
|
|
47
48
|
//#endregion
|
|
@@ -111,6 +112,7 @@ async function getContextMetadata() {
|
|
|
111
112
|
"codemetaJson",
|
|
112
113
|
"gitConfig",
|
|
113
114
|
"githubActions",
|
|
115
|
+
"gitStats",
|
|
114
116
|
"goGoMod",
|
|
115
117
|
"goGoreleaserYaml",
|
|
116
118
|
"javaPomXml",
|
|
@@ -140,8 +142,9 @@ async function getContextMetadata() {
|
|
|
140
142
|
const GIT_PREFIX_REGEX = /^git\+/v;
|
|
141
143
|
const GIT_SUFFIX_REGEX = /\.git$/v;
|
|
142
144
|
const TRAILING_SLASH_REGEX = /\/$/v;
|
|
145
|
+
const PACKAGE_MANAGER_REGEX = /^(?<name>[^@]+)@(?<version>[^+]+)/v;
|
|
143
146
|
const readmeMetadataTemplate = defineTemplate((context) => {
|
|
144
|
-
const { githubActions, licenseFile, metascope, nodePackageJson } = context;
|
|
147
|
+
const { githubActions, gitStats, licenseFile, metascope, nodePackageJson } = context;
|
|
145
148
|
const codemeta = templates.codemetaJson(context, {});
|
|
146
149
|
const nodePackage = helpers.firstOf(nodePackageJson)?.data;
|
|
147
150
|
const licenseFileData = helpers.firstOf(licenseFile);
|
|
@@ -174,6 +177,27 @@ const readmeMetadataTemplate = defineTemplate((context) => {
|
|
|
174
177
|
version
|
|
175
178
|
}));
|
|
176
179
|
})();
|
|
180
|
+
const developmentDependencies = (() => {
|
|
181
|
+
if (nodePackage === void 0) return;
|
|
182
|
+
const runtimes = helpers.ensureArray(nodePackage.devEngines?.runtime).map(({ name, version }) => ({
|
|
183
|
+
name,
|
|
184
|
+
version
|
|
185
|
+
}));
|
|
186
|
+
const packageManagers = helpers.ensureArray(nodePackage.devEngines?.packageManager).map(({ name, version }) => ({
|
|
187
|
+
name,
|
|
188
|
+
version
|
|
189
|
+
}));
|
|
190
|
+
const pinnedPackageManager = nodePackage.packageManager === void 0 ? void 0 : PACKAGE_MANAGER_REGEX.exec(nodePackage.packageManager)?.groups;
|
|
191
|
+
if (pinnedPackageManager?.name !== void 0 && pinnedPackageManager.version !== void 0 && packageManagers.every((entry) => entry.name !== pinnedPackageManager.name)) packageManagers.push({
|
|
192
|
+
name: pinnedPackageManager.name,
|
|
193
|
+
version: pinnedPackageManager.version
|
|
194
|
+
});
|
|
195
|
+
if (runtimes.length === 0 && packageManagers.length === 0) return;
|
|
196
|
+
return {
|
|
197
|
+
packageManagers: packageManagers.length > 0 ? packageManagers : void 0,
|
|
198
|
+
runtimes: runtimes.length > 0 ? runtimes : void 0
|
|
199
|
+
};
|
|
200
|
+
})();
|
|
177
201
|
const firstAuthor = helpers.firstOf(helpers.ensureArray(codemeta.author));
|
|
178
202
|
return {
|
|
179
203
|
author: helpers.firstOf(helpers.mixedStringsToArray(helpers.toBasicNames(codemeta.author))),
|
|
@@ -181,6 +205,7 @@ const readmeMetadataTemplate = defineTemplate((context) => {
|
|
|
181
205
|
bin,
|
|
182
206
|
ciActionFileName: ciActionFilePath === void 0 ? void 0 : path.basename(ciActionFilePath),
|
|
183
207
|
description: codemeta.description,
|
|
208
|
+
developmentDependencies,
|
|
184
209
|
engines,
|
|
185
210
|
isPublicNpmPackage: nodePackage?.private !== true && (nodePackage?.name.startsWith("@") && nodePackage.publishConfig?.access === "public" || true),
|
|
186
211
|
issuesUrl: codemeta.issueTracker,
|
|
@@ -193,6 +218,7 @@ const readmeMetadataTemplate = defineTemplate((context) => {
|
|
|
193
218
|
projectDirectory: metascope?.data.options.path === void 0 ? void 0 : `file://${metascope.data.options.path}`,
|
|
194
219
|
repositoryUrl: repoUrl,
|
|
195
220
|
runtimePlatform: codemeta.runtimePlatform,
|
|
221
|
+
usesGitLfs: helpers.firstOf(gitStats)?.data.hasLfs === true,
|
|
196
222
|
usesPnpm: helpers.usesPnpm(nodePackageJson)
|
|
197
223
|
};
|
|
198
224
|
});
|
|
@@ -220,13 +246,14 @@ var badges_default = { badges: { async content(options) {
|
|
|
220
246
|
npm: z.array(z.string()).optional()
|
|
221
247
|
}).optional().parse(options);
|
|
222
248
|
const metadata = await getReadmeMetadata();
|
|
223
|
-
const { ciActionFileName, license, licenseUrl, name, repositoryUrl } = metadata;
|
|
249
|
+
const { ciActionFileName, license, licenseUrl, name, repositoryUrl, usesGitLfs } = metadata;
|
|
224
250
|
const badges = [];
|
|
225
251
|
if (validOptions?.npm === void 0) {
|
|
226
252
|
if (metadata.isPublicNpmPackage) badges.push(`[](https://www.npmjs.com/package/${name})`);
|
|
227
253
|
} else for (const packageName of validOptions.npm) badges.push(`[](https://www.npmjs.com/package/${packageName})`);
|
|
228
254
|
if (license !== void 0 && licenseUrl !== void 0) badges.push(`[}-yellow.svg)](${licenseUrl})`);
|
|
229
255
|
if (ciActionFileName !== void 0 && repositoryUrl !== void 0) badges.push(`[](${repositoryUrl}/actions/workflows/${ciActionFileName})`);
|
|
256
|
+
if (usesGitLfs) badges.push("");
|
|
230
257
|
if (validOptions?.custom !== void 0) for (const [badgeName, { image, link }] of Object.entries(validOptions.custom)) badges.push(`[](${link})`);
|
|
231
258
|
return badges.join("\n");
|
|
232
259
|
} } };
|
|
@@ -349,7 +376,7 @@ const PLATFORM_INFO = {
|
|
|
349
376
|
},
|
|
350
377
|
node: {
|
|
351
378
|
display: "Node.js",
|
|
352
|
-
url: "https://nodejs.org/"
|
|
379
|
+
url: "https://nodejs.org/en"
|
|
353
380
|
},
|
|
354
381
|
python: {
|
|
355
382
|
display: "Python",
|
|
@@ -409,6 +436,58 @@ var description_default = { description: { async content() {
|
|
|
409
436
|
return `**${description}**`;
|
|
410
437
|
} } };
|
|
411
438
|
|
|
439
|
+
//#endregion
|
|
440
|
+
//#region src/lib/readme/rules/development-dependencies.ts
|
|
441
|
+
const TOOL_INFO = {
|
|
442
|
+
bun: {
|
|
443
|
+
display: "Bun",
|
|
444
|
+
url: "https://bun.sh/"
|
|
445
|
+
},
|
|
446
|
+
deno: {
|
|
447
|
+
display: "Deno",
|
|
448
|
+
url: "https://deno.land/"
|
|
449
|
+
},
|
|
450
|
+
node: {
|
|
451
|
+
display: "Node.js",
|
|
452
|
+
url: "https://nodejs.org/en"
|
|
453
|
+
},
|
|
454
|
+
npm: {
|
|
455
|
+
display: "npm",
|
|
456
|
+
url: "https://www.npmjs.com/"
|
|
457
|
+
},
|
|
458
|
+
pnpm: {
|
|
459
|
+
display: "pnpm",
|
|
460
|
+
url: "https://pnpm.io/"
|
|
461
|
+
},
|
|
462
|
+
yarn: {
|
|
463
|
+
display: "Yarn",
|
|
464
|
+
url: "https://yarnpkg.com/"
|
|
465
|
+
}
|
|
466
|
+
};
|
|
467
|
+
var development_dependencies_default = { "development-dependencies": { async content() {
|
|
468
|
+
const { developmentDependencies } = await getReadmeMetadata();
|
|
469
|
+
if (developmentDependencies === void 0) return "";
|
|
470
|
+
const { packageManagers, runtimes } = developmentDependencies;
|
|
471
|
+
const items = [];
|
|
472
|
+
for (const { name, version } of [...runtimes ?? [], ...packageManagers ?? []]) {
|
|
473
|
+
const info = TOOL_INFO[name.toLowerCase()];
|
|
474
|
+
const display = info ? `[${info.display}](${info.url})` : name;
|
|
475
|
+
items.push(version === void 0 || version === "" ? `- ${display}` : `- ${display} ${version}`);
|
|
476
|
+
}
|
|
477
|
+
return [
|
|
478
|
+
"## Development Dependencies",
|
|
479
|
+
"",
|
|
480
|
+
...items
|
|
481
|
+
].join("\n");
|
|
482
|
+
} } };
|
|
483
|
+
|
|
484
|
+
//#endregion
|
|
485
|
+
//#region src/lib/readme/rules/dev-dependencies.ts
|
|
486
|
+
/**
|
|
487
|
+
* Simple alias for `development-dependencies`
|
|
488
|
+
*/
|
|
489
|
+
var dev_dependencies_default = { "dev-dependencies": getSoleRule(development_dependencies_default) };
|
|
490
|
+
|
|
412
491
|
//#endregion
|
|
413
492
|
//#region src/lib/readme/rules/license.ts
|
|
414
493
|
var license_default = { license: { async content() {
|
|
@@ -492,11 +571,11 @@ const gzipCompressAsync = promisify(gzip);
|
|
|
492
571
|
* @param bytes - Size in bytes
|
|
493
572
|
* @param originalSize - Original file size for percentage calculation
|
|
494
573
|
*/
|
|
495
|
-
function createSizeInfo(bytes, originalSize) {
|
|
574
|
+
function createSizeInfo(bytes, originalSize, precision) {
|
|
496
575
|
const percent = originalSize === 0 ? 0 : (originalSize - bytes) / originalSize * 100;
|
|
497
576
|
return {
|
|
498
577
|
bytes,
|
|
499
|
-
bytesPretty: prettyBytes(bytes, { maximumFractionDigits:
|
|
578
|
+
bytesPretty: prettyBytes(bytes, { maximumFractionDigits: precision }),
|
|
500
579
|
percent,
|
|
501
580
|
percentPretty: `${Math.round(percent)}%`
|
|
502
581
|
};
|
|
@@ -505,19 +584,20 @@ function createSizeInfo(bytes, originalSize) {
|
|
|
505
584
|
* Analyzes a file's size and its compressed sizes using Brotli and Gzip
|
|
506
585
|
*
|
|
507
586
|
* @param filePath - Path to the file to analyze
|
|
587
|
+
* @param precision - Maximum number of decimal places in formatted byte sizes
|
|
508
588
|
*
|
|
509
589
|
* @returns Promise containing detailed size report
|
|
510
590
|
* @throws {Error} If file cannot be read or compressed
|
|
511
591
|
*/
|
|
512
|
-
async function createSizeReport(filePath) {
|
|
592
|
+
async function createSizeReport(filePath, precision = 1) {
|
|
513
593
|
try {
|
|
514
594
|
const fileContent = await fs.readFile(filePath);
|
|
515
595
|
const originalSize = fileContent.length;
|
|
516
596
|
const [brotliCompressed, gzipCompressed] = await Promise.all([brotliCompressAsync(fileContent), gzipCompressAsync(fileContent)]);
|
|
517
597
|
return {
|
|
518
|
-
brotli: createSizeInfo(brotliCompressed.length, originalSize),
|
|
519
|
-
gzip: createSizeInfo(gzipCompressed.length, originalSize),
|
|
520
|
-
original: createSizeInfo(originalSize, originalSize)
|
|
598
|
+
brotli: createSizeInfo(brotliCompressed.length, originalSize, precision),
|
|
599
|
+
gzip: createSizeInfo(gzipCompressed.length, originalSize, precision),
|
|
600
|
+
original: createSizeInfo(originalSize, originalSize, precision)
|
|
521
601
|
};
|
|
522
602
|
} catch (error) {
|
|
523
603
|
throw new Error(`Failed to analyze file: ${error instanceof Error ? error.message : "Unknown error"}`, { cause: error });
|
|
@@ -543,7 +623,8 @@ function getSizeForCompression(report, compression) {
|
|
|
543
623
|
}
|
|
544
624
|
var size_default = { size: { async content(options) {
|
|
545
625
|
const validOptions = optionsSchema$1.parse(options);
|
|
546
|
-
|
|
626
|
+
const fullPath = path.join(process.cwd(), validOptions.file);
|
|
627
|
+
return getSizeForCompression(await createSizeReport(fullPath), validOptions.compression);
|
|
547
628
|
} } };
|
|
548
629
|
|
|
549
630
|
//#endregion
|
|
@@ -554,12 +635,14 @@ const optionsSchema = z.union([z.object({
|
|
|
554
635
|
file: fileSchema,
|
|
555
636
|
gzip: z.boolean().optional().default(true),
|
|
556
637
|
original: z.boolean().optional().default(true),
|
|
638
|
+
precision: z.number().int().min(0).max(100).optional().default(0),
|
|
557
639
|
showPercentage: z.boolean().optional().default(false)
|
|
558
640
|
}), z.object({
|
|
559
641
|
brotli: z.boolean().optional().default(true),
|
|
560
642
|
files: fileSchema,
|
|
561
643
|
gzip: z.boolean().optional().default(true),
|
|
562
644
|
original: z.boolean().optional().default(true),
|
|
645
|
+
precision: z.number().int().min(0).max(100).optional().default(0),
|
|
563
646
|
showPercentage: z.boolean().optional().default(false)
|
|
564
647
|
})]).transform((options) => {
|
|
565
648
|
if ("file" in options) {
|
|
@@ -593,7 +676,8 @@ function formatMarkdownTable(reports, options) {
|
|
|
593
676
|
var size_table_default = { "size-table": { async content(options) {
|
|
594
677
|
const validOptions = optionsSchema.parse(options);
|
|
595
678
|
return formatMarkdownTable(await Promise.all(validOptions.files.map(async (file) => {
|
|
596
|
-
|
|
679
|
+
const fullPath = path.join(process.cwd(), file);
|
|
680
|
+
return [file, await createSizeReport(fullPath, validOptions.precision)];
|
|
597
681
|
})), {
|
|
598
682
|
brotli: validOptions.brotli,
|
|
599
683
|
gzip: validOptions.gzip,
|
|
@@ -606,16 +690,17 @@ var size_table_default = { "size-table": { async content(options) {
|
|
|
606
690
|
//#region src/lib/readme/rules/table-of-contents.ts
|
|
607
691
|
var table_of_contents_default = { "table-of-contents": {
|
|
608
692
|
async content(options, { tree }) {
|
|
693
|
+
const validOptions = z.object({ depth: z.union([
|
|
694
|
+
z.literal(1),
|
|
695
|
+
z.literal(2),
|
|
696
|
+
z.literal(3),
|
|
697
|
+
z.literal(4),
|
|
698
|
+
z.literal(5),
|
|
699
|
+
z.literal(6)
|
|
700
|
+
]).optional() }).optional().parse(options);
|
|
609
701
|
const result = toc(tree, {
|
|
610
702
|
heading: null,
|
|
611
|
-
maxDepth:
|
|
612
|
-
z.literal(1),
|
|
613
|
-
z.literal(2),
|
|
614
|
-
z.literal(3),
|
|
615
|
-
z.literal(4),
|
|
616
|
-
z.literal(5),
|
|
617
|
-
z.literal(6)
|
|
618
|
-
]).optional() }).optional().parse(options)?.depth ?? 3,
|
|
703
|
+
maxDepth: validOptions?.depth ?? 3,
|
|
619
704
|
tight: true
|
|
620
705
|
});
|
|
621
706
|
if (result.map === void 0) throw new Error("Could not generate table of contents");
|
|
@@ -645,6 +730,8 @@ var rules_default = {
|
|
|
645
730
|
...contributing_default,
|
|
646
731
|
...dependencies_default,
|
|
647
732
|
...description_default,
|
|
733
|
+
...dev_dependencies_default,
|
|
734
|
+
...development_dependencies_default,
|
|
648
735
|
...footer_default,
|
|
649
736
|
...header_default,
|
|
650
737
|
...install_default,
|
|
@@ -700,11 +787,13 @@ async function loadConfig(options) {
|
|
|
700
787
|
let loaded;
|
|
701
788
|
if (typeof configOrPath === "string") {
|
|
702
789
|
let loadResults;
|
|
703
|
-
if (path.basename(configOrPath).endsWith("package.json"))
|
|
704
|
-
|
|
705
|
-
|
|
706
|
-
|
|
707
|
-
|
|
790
|
+
if (path.basename(configOrPath).endsWith("package.json")) {
|
|
791
|
+
const packageJson = await fs.readFile(configOrPath, "utf8");
|
|
792
|
+
loadResults = {
|
|
793
|
+
config: mdatJsonLoader(configOrPath, packageJson),
|
|
794
|
+
filepath: configOrPath
|
|
795
|
+
};
|
|
796
|
+
} else loadResults = await getAdditionalConfigExplorer().load(configOrPath);
|
|
708
797
|
if (loadResults === null || loadResults === void 0) continue;
|
|
709
798
|
const { config: loadedConfig, filepath } = loadResults;
|
|
710
799
|
log.debug(`Loaded additional config from "${filepath}"`);
|
|
@@ -867,7 +956,8 @@ function stripLintPlugins(config) {
|
|
|
867
956
|
//#region src/lib/processors.ts
|
|
868
957
|
async function processFiles(files, loader, processorGetter, name, output, config) {
|
|
869
958
|
const [resolvedConfig, localRemarkConfig] = await Promise.all([loader({ additionalConfig: config }), loadAmbientRemarkConfig()]);
|
|
870
|
-
const
|
|
959
|
+
const resolvedFiles = ensureArray(files);
|
|
960
|
+
const inputOutputPaths = await getInputOutputPaths(resolvedFiles, output, name, "md");
|
|
871
961
|
const resolvedProcessor = processorGetter(resolvedConfig, localRemarkConfig);
|
|
872
962
|
return await Promise.all(inputOutputPaths.map(async ({ input, name: outputName, output: outputDirectory }) => {
|
|
873
963
|
const inputFile = await read(input);
|
|
@@ -1222,7 +1312,8 @@ try {
|
|
|
1222
1312
|
output,
|
|
1223
1313
|
print
|
|
1224
1314
|
});
|
|
1225
|
-
const
|
|
1315
|
+
const mergedConfig = collectConfig(config);
|
|
1316
|
+
const results = await expand(files, fileName, output, mergedConfig, { format });
|
|
1226
1317
|
for (const file of results) if (print) process.stdout.write(file.toString());
|
|
1227
1318
|
else await write(file);
|
|
1228
1319
|
reporterMdat(results);
|
|
@@ -1253,7 +1344,8 @@ try {
|
|
|
1253
1344
|
log.debug(`Stripped comments in ${prettyMilliseconds(performance.now() - startTime)}.`);
|
|
1254
1345
|
process.exitCode = getExitCode(results);
|
|
1255
1346
|
}).command("check [files..] [options]", "Check if MDAT placeholder comments are up to date. Exits with code 1 if any files have stale or unexpanded content.", (commandYargs) => commandYargs.positional(...filesPositional).option(configOption).option(formatOption), async ({ config, files, format }) => {
|
|
1256
|
-
const
|
|
1347
|
+
const mergedConfig = collectConfig(config);
|
|
1348
|
+
const results = await check(files, mergedConfig, { format });
|
|
1257
1349
|
let allInSync = true;
|
|
1258
1350
|
for (const { inSync, result } of results) {
|
|
1259
1351
|
const filePath = result.path === "" ? "unknown" : result.path;
|
package/dist/lib/index.d.ts
CHANGED
|
@@ -156,6 +156,16 @@ declare const readmeMetadataTemplate: import("metascope").Template<{
|
|
|
156
156
|
bin: string[] | undefined;
|
|
157
157
|
ciActionFileName: string | undefined;
|
|
158
158
|
description: string | undefined;
|
|
159
|
+
developmentDependencies: {
|
|
160
|
+
packageManagers: {
|
|
161
|
+
name: string;
|
|
162
|
+
version: string | undefined;
|
|
163
|
+
}[] | undefined;
|
|
164
|
+
runtimes: {
|
|
165
|
+
name: string;
|
|
166
|
+
version: string | undefined;
|
|
167
|
+
}[] | undefined;
|
|
168
|
+
} | undefined;
|
|
159
169
|
engines: {
|
|
160
170
|
[k: string]: string;
|
|
161
171
|
} | undefined;
|
|
@@ -174,6 +184,7 @@ declare const readmeMetadataTemplate: import("metascope").Template<{
|
|
|
174
184
|
projectDirectory: string | undefined;
|
|
175
185
|
repositoryUrl: string | undefined;
|
|
176
186
|
runtimePlatform: string[] | undefined;
|
|
187
|
+
usesGitLfs: boolean;
|
|
177
188
|
usesPnpm: boolean;
|
|
178
189
|
}>;
|
|
179
190
|
type ReadmeMetadata = ReturnType<typeof readmeMetadataTemplate>;
|
|
@@ -188,6 +199,16 @@ declare function getReadmeMetadata(): Promise<{
|
|
|
188
199
|
bin: string[] | undefined;
|
|
189
200
|
ciActionFileName: string | undefined;
|
|
190
201
|
description: string | undefined;
|
|
202
|
+
developmentDependencies: {
|
|
203
|
+
packageManagers: {
|
|
204
|
+
name: string;
|
|
205
|
+
version: string | undefined;
|
|
206
|
+
}[] | undefined;
|
|
207
|
+
runtimes: {
|
|
208
|
+
name: string;
|
|
209
|
+
version: string | undefined;
|
|
210
|
+
}[] | undefined;
|
|
211
|
+
} | undefined;
|
|
191
212
|
engines: {
|
|
192
213
|
[k: string]: string;
|
|
193
214
|
} | undefined;
|
|
@@ -206,6 +227,7 @@ declare function getReadmeMetadata(): Promise<{
|
|
|
206
227
|
projectDirectory: string | undefined;
|
|
207
228
|
repositoryUrl: string | undefined;
|
|
208
229
|
runtimePlatform: string[] | undefined;
|
|
230
|
+
usesGitLfs: boolean;
|
|
209
231
|
usesPnpm: boolean;
|
|
210
232
|
}>;
|
|
211
233
|
/**
|
package/dist/lib/index.js
CHANGED
|
@@ -31,7 +31,8 @@ function stripUndefinedDeep(object) {
|
|
|
31
31
|
}, {});
|
|
32
32
|
}
|
|
33
33
|
function deepMergeDefined(...objects) {
|
|
34
|
-
|
|
34
|
+
const stripped = objects.map((v, i) => i === 0 ? v : stripUndefinedDeep(v));
|
|
35
|
+
return deepmerge(...stripped);
|
|
35
36
|
}
|
|
36
37
|
//#endregion
|
|
37
38
|
//#region src/lib/log.ts
|
|
@@ -98,6 +99,7 @@ async function getContextMetadata() {
|
|
|
98
99
|
"codemetaJson",
|
|
99
100
|
"gitConfig",
|
|
100
101
|
"githubActions",
|
|
102
|
+
"gitStats",
|
|
101
103
|
"goGoMod",
|
|
102
104
|
"goGoreleaserYaml",
|
|
103
105
|
"javaPomXml",
|
|
@@ -127,6 +129,7 @@ async function getContextMetadata() {
|
|
|
127
129
|
const GIT_PREFIX_REGEX = /^git\+/v;
|
|
128
130
|
const GIT_SUFFIX_REGEX = /\.git$/v;
|
|
129
131
|
const TRAILING_SLASH_REGEX = /\/$/v;
|
|
132
|
+
const PACKAGE_MANAGER_REGEX = /^(?<name>[^@]+)@(?<version>[^+]+)/v;
|
|
130
133
|
/**
|
|
131
134
|
* Reset cached context metadata. Call between tests or when the underlying
|
|
132
135
|
* project files may have changed on disk.
|
|
@@ -137,7 +140,7 @@ function resetContextMetadata() {
|
|
|
137
140
|
metascopeMetadata = void 0;
|
|
138
141
|
}
|
|
139
142
|
const readmeMetadataTemplate = defineTemplate((context) => {
|
|
140
|
-
const { githubActions, licenseFile, metascope, nodePackageJson } = context;
|
|
143
|
+
const { githubActions, gitStats, licenseFile, metascope, nodePackageJson } = context;
|
|
141
144
|
const codemeta = templates.codemetaJson(context, {});
|
|
142
145
|
const nodePackage = helpers.firstOf(nodePackageJson)?.data;
|
|
143
146
|
const licenseFileData = helpers.firstOf(licenseFile);
|
|
@@ -170,6 +173,27 @@ const readmeMetadataTemplate = defineTemplate((context) => {
|
|
|
170
173
|
version
|
|
171
174
|
}));
|
|
172
175
|
})();
|
|
176
|
+
const developmentDependencies = (() => {
|
|
177
|
+
if (nodePackage === void 0) return;
|
|
178
|
+
const runtimes = helpers.ensureArray(nodePackage.devEngines?.runtime).map(({ name, version }) => ({
|
|
179
|
+
name,
|
|
180
|
+
version
|
|
181
|
+
}));
|
|
182
|
+
const packageManagers = helpers.ensureArray(nodePackage.devEngines?.packageManager).map(({ name, version }) => ({
|
|
183
|
+
name,
|
|
184
|
+
version
|
|
185
|
+
}));
|
|
186
|
+
const pinnedPackageManager = nodePackage.packageManager === void 0 ? void 0 : PACKAGE_MANAGER_REGEX.exec(nodePackage.packageManager)?.groups;
|
|
187
|
+
if (pinnedPackageManager?.name !== void 0 && pinnedPackageManager.version !== void 0 && packageManagers.every((entry) => entry.name !== pinnedPackageManager.name)) packageManagers.push({
|
|
188
|
+
name: pinnedPackageManager.name,
|
|
189
|
+
version: pinnedPackageManager.version
|
|
190
|
+
});
|
|
191
|
+
if (runtimes.length === 0 && packageManagers.length === 0) return;
|
|
192
|
+
return {
|
|
193
|
+
packageManagers: packageManagers.length > 0 ? packageManagers : void 0,
|
|
194
|
+
runtimes: runtimes.length > 0 ? runtimes : void 0
|
|
195
|
+
};
|
|
196
|
+
})();
|
|
173
197
|
const firstAuthor = helpers.firstOf(helpers.ensureArray(codemeta.author));
|
|
174
198
|
return {
|
|
175
199
|
author: helpers.firstOf(helpers.mixedStringsToArray(helpers.toBasicNames(codemeta.author))),
|
|
@@ -177,6 +201,7 @@ const readmeMetadataTemplate = defineTemplate((context) => {
|
|
|
177
201
|
bin,
|
|
178
202
|
ciActionFileName: ciActionFilePath === void 0 ? void 0 : path.basename(ciActionFilePath),
|
|
179
203
|
description: codemeta.description,
|
|
204
|
+
developmentDependencies,
|
|
180
205
|
engines,
|
|
181
206
|
isPublicNpmPackage: nodePackage?.private !== true && (nodePackage?.name.startsWith("@") && nodePackage.publishConfig?.access === "public" || true),
|
|
182
207
|
issuesUrl: codemeta.issueTracker,
|
|
@@ -189,6 +214,7 @@ const readmeMetadataTemplate = defineTemplate((context) => {
|
|
|
189
214
|
projectDirectory: metascope?.data.options.path === void 0 ? void 0 : `file://${metascope.data.options.path}`,
|
|
190
215
|
repositoryUrl: repoUrl,
|
|
191
216
|
runtimePlatform: codemeta.runtimePlatform,
|
|
217
|
+
usesGitLfs: helpers.firstOf(gitStats)?.data.hasLfs === true,
|
|
192
218
|
usesPnpm: helpers.usesPnpm(nodePackageJson)
|
|
193
219
|
};
|
|
194
220
|
});
|
|
@@ -232,13 +258,14 @@ var badges_default = { badges: { async content(options) {
|
|
|
232
258
|
npm: z.array(z.string()).optional()
|
|
233
259
|
}).optional().parse(options);
|
|
234
260
|
const metadata = await getReadmeMetadata();
|
|
235
|
-
const { ciActionFileName, license, licenseUrl, name, repositoryUrl } = metadata;
|
|
261
|
+
const { ciActionFileName, license, licenseUrl, name, repositoryUrl, usesGitLfs } = metadata;
|
|
236
262
|
const badges = [];
|
|
237
263
|
if (validOptions?.npm === void 0) {
|
|
238
264
|
if (metadata.isPublicNpmPackage) badges.push(`[](https://www.npmjs.com/package/${name})`);
|
|
239
265
|
} else for (const packageName of validOptions.npm) badges.push(`[](https://www.npmjs.com/package/${packageName})`);
|
|
240
266
|
if (license !== void 0 && licenseUrl !== void 0) badges.push(`[}-yellow.svg)](${licenseUrl})`);
|
|
241
267
|
if (ciActionFileName !== void 0 && repositoryUrl !== void 0) badges.push(`[](${repositoryUrl}/actions/workflows/${ciActionFileName})`);
|
|
268
|
+
if (usesGitLfs) badges.push("");
|
|
242
269
|
if (validOptions?.custom !== void 0) for (const [badgeName, { image, link }] of Object.entries(validOptions.custom)) badges.push(`[](${link})`);
|
|
243
270
|
return badges.join("\n");
|
|
244
271
|
} } };
|
|
@@ -357,7 +384,7 @@ const PLATFORM_INFO = {
|
|
|
357
384
|
},
|
|
358
385
|
node: {
|
|
359
386
|
display: "Node.js",
|
|
360
|
-
url: "https://nodejs.org/"
|
|
387
|
+
url: "https://nodejs.org/en"
|
|
361
388
|
},
|
|
362
389
|
python: {
|
|
363
390
|
display: "Python",
|
|
@@ -416,6 +443,56 @@ var description_default = { description: { async content() {
|
|
|
416
443
|
return `**${description}**`;
|
|
417
444
|
} } };
|
|
418
445
|
//#endregion
|
|
446
|
+
//#region src/lib/readme/rules/development-dependencies.ts
|
|
447
|
+
const TOOL_INFO = {
|
|
448
|
+
bun: {
|
|
449
|
+
display: "Bun",
|
|
450
|
+
url: "https://bun.sh/"
|
|
451
|
+
},
|
|
452
|
+
deno: {
|
|
453
|
+
display: "Deno",
|
|
454
|
+
url: "https://deno.land/"
|
|
455
|
+
},
|
|
456
|
+
node: {
|
|
457
|
+
display: "Node.js",
|
|
458
|
+
url: "https://nodejs.org/en"
|
|
459
|
+
},
|
|
460
|
+
npm: {
|
|
461
|
+
display: "npm",
|
|
462
|
+
url: "https://www.npmjs.com/"
|
|
463
|
+
},
|
|
464
|
+
pnpm: {
|
|
465
|
+
display: "pnpm",
|
|
466
|
+
url: "https://pnpm.io/"
|
|
467
|
+
},
|
|
468
|
+
yarn: {
|
|
469
|
+
display: "Yarn",
|
|
470
|
+
url: "https://yarnpkg.com/"
|
|
471
|
+
}
|
|
472
|
+
};
|
|
473
|
+
var development_dependencies_default = { "development-dependencies": { async content() {
|
|
474
|
+
const { developmentDependencies } = await getReadmeMetadata();
|
|
475
|
+
if (developmentDependencies === void 0) return "";
|
|
476
|
+
const { packageManagers, runtimes } = developmentDependencies;
|
|
477
|
+
const items = [];
|
|
478
|
+
for (const { name, version } of [...runtimes ?? [], ...packageManagers ?? []]) {
|
|
479
|
+
const info = TOOL_INFO[name.toLowerCase()];
|
|
480
|
+
const display = info ? `[${info.display}](${info.url})` : name;
|
|
481
|
+
items.push(version === void 0 || version === "" ? `- ${display}` : `- ${display} ${version}`);
|
|
482
|
+
}
|
|
483
|
+
return [
|
|
484
|
+
"## Development Dependencies",
|
|
485
|
+
"",
|
|
486
|
+
...items
|
|
487
|
+
].join("\n");
|
|
488
|
+
} } };
|
|
489
|
+
//#endregion
|
|
490
|
+
//#region src/lib/readme/rules/dev-dependencies.ts
|
|
491
|
+
/**
|
|
492
|
+
* Simple alias for `development-dependencies`
|
|
493
|
+
*/
|
|
494
|
+
var dev_dependencies_default = { "dev-dependencies": getSoleRule(development_dependencies_default) };
|
|
495
|
+
//#endregion
|
|
419
496
|
//#region src/lib/readme/rules/license.ts
|
|
420
497
|
var license_default = { license: { async content() {
|
|
421
498
|
const { author, authorUrl, license, licenseFilePath } = await getReadmeMetadata();
|
|
@@ -492,11 +569,11 @@ const gzipCompressAsync = promisify(gzip);
|
|
|
492
569
|
* @param bytes - Size in bytes
|
|
493
570
|
* @param originalSize - Original file size for percentage calculation
|
|
494
571
|
*/
|
|
495
|
-
function createSizeInfo(bytes, originalSize) {
|
|
572
|
+
function createSizeInfo(bytes, originalSize, precision) {
|
|
496
573
|
const percent = originalSize === 0 ? 0 : (originalSize - bytes) / originalSize * 100;
|
|
497
574
|
return {
|
|
498
575
|
bytes,
|
|
499
|
-
bytesPretty: prettyBytes(bytes, { maximumFractionDigits:
|
|
576
|
+
bytesPretty: prettyBytes(bytes, { maximumFractionDigits: precision }),
|
|
500
577
|
percent,
|
|
501
578
|
percentPretty: `${Math.round(percent)}%`
|
|
502
579
|
};
|
|
@@ -505,19 +582,20 @@ function createSizeInfo(bytes, originalSize) {
|
|
|
505
582
|
* Analyzes a file's size and its compressed sizes using Brotli and Gzip
|
|
506
583
|
*
|
|
507
584
|
* @param filePath - Path to the file to analyze
|
|
585
|
+
* @param precision - Maximum number of decimal places in formatted byte sizes
|
|
508
586
|
*
|
|
509
587
|
* @returns Promise containing detailed size report
|
|
510
588
|
* @throws {Error} If file cannot be read or compressed
|
|
511
589
|
*/
|
|
512
|
-
async function createSizeReport(filePath) {
|
|
590
|
+
async function createSizeReport(filePath, precision = 1) {
|
|
513
591
|
try {
|
|
514
592
|
const fileContent = await fs.readFile(filePath);
|
|
515
593
|
const originalSize = fileContent.length;
|
|
516
594
|
const [brotliCompressed, gzipCompressed] = await Promise.all([brotliCompressAsync(fileContent), gzipCompressAsync(fileContent)]);
|
|
517
595
|
return {
|
|
518
|
-
brotli: createSizeInfo(brotliCompressed.length, originalSize),
|
|
519
|
-
gzip: createSizeInfo(gzipCompressed.length, originalSize),
|
|
520
|
-
original: createSizeInfo(originalSize, originalSize)
|
|
596
|
+
brotli: createSizeInfo(brotliCompressed.length, originalSize, precision),
|
|
597
|
+
gzip: createSizeInfo(gzipCompressed.length, originalSize, precision),
|
|
598
|
+
original: createSizeInfo(originalSize, originalSize, precision)
|
|
521
599
|
};
|
|
522
600
|
} catch (error) {
|
|
523
601
|
throw new Error(`Failed to analyze file: ${error instanceof Error ? error.message : "Unknown error"}`, { cause: error });
|
|
@@ -552,12 +630,14 @@ const optionsSchema = z.union([z.object({
|
|
|
552
630
|
file: fileSchema,
|
|
553
631
|
gzip: z.boolean().optional().default(true),
|
|
554
632
|
original: z.boolean().optional().default(true),
|
|
633
|
+
precision: z.number().int().min(0).max(100).optional().default(0),
|
|
555
634
|
showPercentage: z.boolean().optional().default(false)
|
|
556
635
|
}), z.object({
|
|
557
636
|
brotli: z.boolean().optional().default(true),
|
|
558
637
|
files: fileSchema,
|
|
559
638
|
gzip: z.boolean().optional().default(true),
|
|
560
639
|
original: z.boolean().optional().default(true),
|
|
640
|
+
precision: z.number().int().min(0).max(100).optional().default(0),
|
|
561
641
|
showPercentage: z.boolean().optional().default(false)
|
|
562
642
|
})]).transform((options) => {
|
|
563
643
|
if ("file" in options) {
|
|
@@ -591,7 +671,7 @@ function formatMarkdownTable(reports, options) {
|
|
|
591
671
|
var size_table_default = { "size-table": { async content(options) {
|
|
592
672
|
const validOptions = optionsSchema.parse(options);
|
|
593
673
|
return formatMarkdownTable(await Promise.all(validOptions.files.map(async (file) => {
|
|
594
|
-
return [file, await createSizeReport(path.join(process.cwd(), file))];
|
|
674
|
+
return [file, await createSizeReport(path.join(process.cwd(), file), validOptions.precision)];
|
|
595
675
|
})), {
|
|
596
676
|
brotli: validOptions.brotli,
|
|
597
677
|
gzip: validOptions.gzip,
|
|
@@ -603,16 +683,17 @@ var size_table_default = { "size-table": { async content(options) {
|
|
|
603
683
|
//#region src/lib/readme/rules/table-of-contents.ts
|
|
604
684
|
var table_of_contents_default = { "table-of-contents": {
|
|
605
685
|
async content(options, { tree }) {
|
|
686
|
+
const validOptions = z.object({ depth: z.union([
|
|
687
|
+
z.literal(1),
|
|
688
|
+
z.literal(2),
|
|
689
|
+
z.literal(3),
|
|
690
|
+
z.literal(4),
|
|
691
|
+
z.literal(5),
|
|
692
|
+
z.literal(6)
|
|
693
|
+
]).optional() }).optional().parse(options);
|
|
606
694
|
const result = toc(tree, {
|
|
607
695
|
heading: null,
|
|
608
|
-
maxDepth:
|
|
609
|
-
z.literal(1),
|
|
610
|
-
z.literal(2),
|
|
611
|
-
z.literal(3),
|
|
612
|
-
z.literal(4),
|
|
613
|
-
z.literal(5),
|
|
614
|
-
z.literal(6)
|
|
615
|
-
]).optional() }).optional().parse(options)?.depth ?? 3,
|
|
696
|
+
maxDepth: validOptions?.depth ?? 3,
|
|
616
697
|
tight: true
|
|
617
698
|
});
|
|
618
699
|
if (result.map === void 0) throw new Error("Could not generate table of contents");
|
|
@@ -640,6 +721,8 @@ var rules_default = {
|
|
|
640
721
|
...contributing_default,
|
|
641
722
|
...dependencies_default,
|
|
642
723
|
...description_default,
|
|
724
|
+
...dev_dependencies_default,
|
|
725
|
+
...development_dependencies_default,
|
|
643
726
|
...footer_default,
|
|
644
727
|
...header_default,
|
|
645
728
|
...install_default,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "mdat",
|
|
3
|
-
"version": "3.
|
|
3
|
+
"version": "3.2.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",
|
|
@@ -44,50 +44,50 @@
|
|
|
44
44
|
],
|
|
45
45
|
"dependencies": {
|
|
46
46
|
"@clack/prompts": "^1.7.0",
|
|
47
|
-
"cosmiconfig": "^
|
|
47
|
+
"cosmiconfig": "^10.0.1",
|
|
48
48
|
"cosmiconfig-typescript-loader": "^6.3.0",
|
|
49
|
-
"deepmerge-ts": "^
|
|
50
|
-
"globby": "^16.2.
|
|
51
|
-
"lognow": "^0.
|
|
49
|
+
"deepmerge-ts": "^8.0.2",
|
|
50
|
+
"globby": "^16.2.4",
|
|
51
|
+
"lognow": "^0.8.0",
|
|
52
52
|
"mdast-util-toc": "^7.1.0",
|
|
53
|
-
"metascope": "^0.
|
|
53
|
+
"metascope": "^0.11.1",
|
|
54
54
|
"path-type": "^6.0.0",
|
|
55
55
|
"picocolors": "^1.1.1",
|
|
56
56
|
"plur": "^6.0.0",
|
|
57
|
-
"pretty-bytes": "^7.1.
|
|
58
|
-
"pretty-ms": "^9.3.
|
|
57
|
+
"pretty-bytes": "^7.1.2",
|
|
58
|
+
"pretty-ms": "^9.3.1",
|
|
59
59
|
"remark": "^15.0.1",
|
|
60
60
|
"remark-gfm": "^4.0.1",
|
|
61
|
-
"remark-mdat": "^3.0.
|
|
61
|
+
"remark-mdat": "^3.0.1",
|
|
62
62
|
"to-vfile": "^8.0.0",
|
|
63
|
-
"type-fest": "^5.
|
|
63
|
+
"type-fest": "^5.9.0",
|
|
64
64
|
"unified-engine": "^11.2.2",
|
|
65
65
|
"untildify": "^6.0.0",
|
|
66
66
|
"vfile": "^6.0.3",
|
|
67
|
-
"yargs": "^18.
|
|
68
|
-
"zod": "^4.4
|
|
67
|
+
"yargs": "^18.1.0",
|
|
68
|
+
"zod": "^4.5.4"
|
|
69
69
|
},
|
|
70
70
|
"devDependencies": {
|
|
71
71
|
"@arethetypeswrong/core": "^0.18.5",
|
|
72
|
-
"@kitschpatrol/shared-config": "^8.
|
|
72
|
+
"@kitschpatrol/shared-config": "^8.7.0",
|
|
73
73
|
"@types/mdast": "^4.0.4",
|
|
74
74
|
"@types/node": "~24.13.3",
|
|
75
75
|
"@types/unist": "^3.0.3",
|
|
76
76
|
"@types/yargs": "^17.0.35",
|
|
77
|
-
"@vitest/coverage-v8": "^4.1.
|
|
78
|
-
"bumpp": "^12.
|
|
79
|
-
"execa": "^10.0.
|
|
80
|
-
"mdat-plugin-cli-help": "^3.0
|
|
81
|
-
"mdat-plugin-example": "^
|
|
82
|
-
"mdat-plugin-tldraw": "^
|
|
83
|
-
"nanoid": "^6.0.
|
|
77
|
+
"@vitest/coverage-v8": "^4.1.11",
|
|
78
|
+
"bumpp": "^12.2.2",
|
|
79
|
+
"execa": "^10.0.1",
|
|
80
|
+
"mdat-plugin-cli-help": "^3.2.0",
|
|
81
|
+
"mdat-plugin-example": "^3.0.0",
|
|
82
|
+
"mdat-plugin-tldraw": "^3.0.0",
|
|
83
|
+
"nanoid": "^6.0.1",
|
|
84
84
|
"prettier": "^3.9.6",
|
|
85
|
-
"publint": "^0.3.
|
|
85
|
+
"publint": "^0.3.24",
|
|
86
86
|
"shx": "^0.4.0",
|
|
87
87
|
"tsdown": "^0.22.14",
|
|
88
88
|
"typescript": "~6.0.3",
|
|
89
|
-
"unplugin-raw": "^0.
|
|
90
|
-
"vitest": "^4.1.
|
|
89
|
+
"unplugin-raw": "^0.8.0",
|
|
90
|
+
"vitest": "^4.1.11"
|
|
91
91
|
},
|
|
92
92
|
"peerDependencies": {
|
|
93
93
|
"prettier": "^3.0.0"
|
|
@@ -108,7 +108,7 @@
|
|
|
108
108
|
"coverage": "vitest --coverage --run",
|
|
109
109
|
"fix": "ksc fix",
|
|
110
110
|
"lint": "ksc lint",
|
|
111
|
-
"release": "bumpp --commit 'Release: %s' && pnpm build &&
|
|
111
|
+
"release": "bumpp --commit 'Release: %s' && pnpm build && pnpm publish --otp $(op item get npm --otp)",
|
|
112
112
|
"test": "vitest run"
|
|
113
113
|
}
|
|
114
114
|
}
|
package/readme.md
CHANGED
|
@@ -6,8 +6,8 @@
|
|
|
6
6
|
|
|
7
7
|
<!-- badges -->
|
|
8
8
|
|
|
9
|
-
[](https://npmjs.com/package/mdat)
|
|
10
|
-
[](https://opensource.org/license/mit
|
|
9
|
+
[](https://www.npmjs.com/package/mdat)
|
|
10
|
+
[](https://opensource.org/license/mit)
|
|
11
11
|
[](https://github.com/kitschpatrol/mdat/actions/workflows/ci.yml)
|
|
12
12
|
|
|
13
13
|
<!-- /badges -->
|
|
@@ -176,7 +176,7 @@ pnpm install --global mdat
|
|
|
176
176
|
}
|
|
177
177
|
```
|
|
178
178
|
|
|
179
|
-
See the [bundled rules](src/lib/readme/rules) for more complex examples.
|
|
179
|
+
See the [bundled rules](./src/lib/readme/rules) for more complex examples.
|
|
180
180
|
|
|
181
181
|
JSON files can also be used as rule sets. MDAT flattens them so any dot-notated key path becomes a comment keyword.
|
|
182
182
|
|
|
@@ -192,7 +192,7 @@ pnpm install --global mdat
|
|
|
192
192
|
|
|
193
193
|
Compound rules combine several individual rules into a single comment keyword.
|
|
194
194
|
|
|
195
|
-
See [`<!-- header -->`](src/lib/readme/rules/header.ts) for an example.
|
|
195
|
+
See [`<!-- header -->`](./src/lib/readme/rules/header.ts) for an example.
|
|
196
196
|
|
|
197
197
|
8. **Polyglot metadata**
|
|
198
198
|
|
|
@@ -548,7 +548,7 @@ When multiple config files are loaded, they are merged. CLI `--config` takes pre
|
|
|
548
548
|
|
|
549
549
|
### Creating custom rules
|
|
550
550
|
|
|
551
|
-
See the [Examples section](https://github.com/kitschpatrol/remark-mdat#examples) of the `remark-mdat` readme, or look at the [bundled rules](src/lib/readme/rules) for complex examples.
|
|
551
|
+
See the [Examples section](https://github.com/kitschpatrol/remark-mdat#examples) of the `remark-mdat` readme, or look at the [bundled rules](./src/lib/readme/rules) for complex examples.
|
|
552
552
|
|
|
553
553
|
### Bundled rules
|
|
554
554
|
|
|
@@ -564,7 +564,7 @@ See the [Examples section](https://github.com/kitschpatrol/remark-mdat#examples)
|
|
|
564
564
|
|
|
565
565
|
- ##### `<!-- badges -->`
|
|
566
566
|
|
|
567
|
-
Generates badges based on project metadata. Supports NPM version, license,
|
|
567
|
+
Generates badges based on project metadata. Supports NPM version, license, CI status, and Git LFS badges.
|
|
568
568
|
|
|
569
569
|
- ##### `<!-- description -->`
|
|
570
570
|
|
|
@@ -578,6 +578,10 @@ See the [Examples section](https://github.com/kitschpatrol/remark-mdat#examples)
|
|
|
578
578
|
|
|
579
579
|
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.
|
|
580
580
|
|
|
581
|
+
- ##### `<!-- development-dependencies -->`
|
|
582
|
+
|
|
583
|
+
Documents the tools needed to work on the project itself, derived from the `devEngines` and `packageManager` fields in `package.json`. Lists required runtimes and package managers with links and version constraints. Also aliased as `<!-- dev-dependencies -->`.
|
|
584
|
+
|
|
581
585
|
- ##### `<!-- table-of-contents -->`
|
|
582
586
|
|
|
583
587
|
Auto-generated via [mdast-util-toc](https://github.com/syntax-tree/mdast-util-toc). Also aliased as `<!-- toc -->`.
|
|
@@ -600,7 +604,7 @@ See the [Examples section](https://github.com/kitschpatrol/remark-mdat#examples)
|
|
|
600
604
|
|
|
601
605
|
- ##### `<!-- size-table({ files: [".gitignore", "license.txt"] }) -->`
|
|
602
606
|
|
|
603
|
-
A table of files and their compressed sizes
|
|
607
|
+
A table of files and their compressed sizes. The optional `precision` sets the maximum number of decimal places and defaults to `0`:
|
|
604
608
|
|
|
605
609
|
<!-- size-table({ files: [".gitignore", "license.txt"] }) -->
|
|
606
610
|
|
|
@@ -792,7 +796,7 @@ There's quite a bit of prior art and similar explorations of this problem space:
|
|
|
792
796
|
- lillallol's [md-in-place](https://www.npmjs.com/package/md-in-place)
|
|
793
797
|
|
|
794
798
|
- [AutoMD](https://automd.unjs.io/)\
|
|
795
|
-
Extremely similar functionality to mdat. The project was initiated around the same time as MDAT, but I didn't find the project until a few years later. Ships in the night.
|
|
799
|
+
Extremely similar functionality to mdat. The project was initiated around the same time as MDAT, but I didn't find the project until a few years later. Ships passing in the night.
|
|
796
800
|
|
|
797
801
|
- Franck Abgrall's [readme-md-generator](https://github.com/kefranabg/readme-md-generator)
|
|
798
802
|
|
|
@@ -802,7 +806,8 @@ There's quite a bit of prior art and similar explorations of this problem space:
|
|
|
802
806
|
|
|
803
807
|
- Hiroki Osame's [comment-mark](https://github.com/privatenumber/comment-mark)
|
|
804
808
|
|
|
805
|
-
- Hiroki Osame's [mdeval](https://github.com/privatenumber/mdeval)
|
|
809
|
+
- Hiroki Osame's [mdeval](https://github.com/privatenumber/mdeval)\
|
|
810
|
+
The best name!
|
|
806
811
|
|
|
807
812
|
### Implementation notes
|
|
808
813
|
|