@stephansama/auto-readme 0.2.7 → 0.2.9
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/cli.mjs +2 -3
- package/config/schema.cjs +16 -19
- package/config/{schema.js → schema.mjs} +13 -16
- package/dist/index.cjs +130 -164
- package/dist/{index.js → index.mjs} +107 -128
- package/package.json +21 -24
- /package/config/{schema.d.ts → schema.d.mts} +0 -0
- /package/dist/{index.d.ts → index.d.mts} +0 -0
|
@@ -1,23 +1,22 @@
|
|
|
1
1
|
import { fromMarkdown } from "mdast-util-from-markdown";
|
|
2
2
|
import * as cp from "node:child_process";
|
|
3
3
|
import * as fsp from "node:fs/promises";
|
|
4
|
-
import
|
|
5
|
-
import
|
|
4
|
+
import { Spinner } from "picospinner";
|
|
5
|
+
import { createDebug, enable } from "obug";
|
|
6
6
|
import yargs from "yargs";
|
|
7
7
|
import { hideBin } from "yargs/helpers";
|
|
8
8
|
import * as z from "zod";
|
|
9
9
|
import { commentMarker } from "mdast-comment-marker";
|
|
10
|
-
import toml from "@iarna/toml";
|
|
11
10
|
import { cosmiconfig, getDefaultSearchPlaces } from "cosmiconfig";
|
|
12
11
|
import deepmerge from "deepmerge";
|
|
12
|
+
import * as toml from "smol-toml";
|
|
13
13
|
import { getPackages } from "@manypkg/get-packages";
|
|
14
14
|
import * as fs from "node:fs";
|
|
15
|
-
import * as path$1 from "node:path";
|
|
16
15
|
import path from "node:path";
|
|
17
16
|
import { readPackageJSON } from "pkg-types";
|
|
18
17
|
import * as yaml from "yaml";
|
|
19
18
|
import { zod2md } from "zod2md";
|
|
20
|
-
import glob from "
|
|
19
|
+
import { glob } from "tinyglobby";
|
|
21
20
|
import { remark } from "remark";
|
|
22
21
|
import remarkCodeImport from "remark-code-import";
|
|
23
22
|
import remarkCollapse from "remark-collapse";
|
|
@@ -27,7 +26,6 @@ import { VFile } from "vfile";
|
|
|
27
26
|
import Handlebars from "handlebars";
|
|
28
27
|
import { markdownTable } from "markdown-table";
|
|
29
28
|
import { zone } from "mdast-zone";
|
|
30
|
-
|
|
31
29
|
//#region src/schema.ts
|
|
32
30
|
const actionsSchema = z.enum([
|
|
33
31
|
"ACTION",
|
|
@@ -70,8 +68,8 @@ const tableHeadingsSchema = z.record(actionsSchema, headingsSchema.array().optio
|
|
|
70
68
|
ZOD: []
|
|
71
69
|
}).meta({ description: "Table heading action configuration" });
|
|
72
70
|
const templatesSchema = z.object({
|
|
73
|
-
downloadImage: z.string().default("https://img.shields.io/npm/dw/{{name}}?labelColor=211F1F"),
|
|
74
|
-
emojis: z.record(headingsSchema, z.string()).default({
|
|
71
|
+
downloadImage: z.string().trim().default("https://img.shields.io/npm/dw/{{name}}?labelColor=211F1F"),
|
|
72
|
+
emojis: z.record(headingsSchema, z.string().trim()).default({
|
|
75
73
|
default: "⚙️",
|
|
76
74
|
description: "📝",
|
|
77
75
|
devDependency: "💻",
|
|
@@ -81,14 +79,14 @@ const templatesSchema = z.object({
|
|
|
81
79
|
required: "",
|
|
82
80
|
version: ""
|
|
83
81
|
}).meta({ description: "Table heading emojis used when enabled" }),
|
|
84
|
-
registryUrl: z.string().default("https://www.npmjs.com/package/{{name}}"),
|
|
85
|
-
versionImage: z.string().default("https://img.shields.io/npm/v/{{uri_name}}?logo=npm&logoColor=red&color=211F1F&labelColor=211F1F")
|
|
82
|
+
registryUrl: z.string().trim().default("https://www.npmjs.com/package/{{name}}"),
|
|
83
|
+
versionImage: z.string().trim().default("https://img.shields.io/npm/v/{{uri_name}}?logo=npm&logoColor=red&color=211F1F&labelColor=211F1F")
|
|
86
84
|
});
|
|
87
85
|
const defaultTemplates = templatesSchema.parse({});
|
|
88
86
|
const defaultTableHeadings = tableHeadingsSchema.parse(void 0);
|
|
89
|
-
const
|
|
90
|
-
affectedRegexes: z.array(z.string()),
|
|
91
|
-
collapseHeadings: z.array(z.string()),
|
|
87
|
+
const configSchema = z.object({
|
|
88
|
+
affectedRegexes: z.array(z.string().trim()),
|
|
89
|
+
collapseHeadings: z.array(z.string().trim()),
|
|
92
90
|
defaultLanguage: languageSchema.meta({
|
|
93
91
|
alias: "l",
|
|
94
92
|
description: "Default language to infer projects from"
|
|
@@ -113,27 +111,25 @@ const _configSchema = z.object({
|
|
|
113
111
|
alias: "p",
|
|
114
112
|
description: "Only show public packages in workspaces"
|
|
115
113
|
}),
|
|
116
|
-
removeScope: z.string().default("").meta({ description: "Remove common workspace scope" }),
|
|
114
|
+
removeScope: z.string().trim().default("").meta({ description: "Remove common workspace scope" }),
|
|
117
115
|
templates: templatesSchema.optional().default(defaultTemplates).describe("Handlebars templates used to fuel list and table generation"),
|
|
118
|
-
tocHeading: z.string().default("Table of contents").meta({ description: "Markdown heading used to generate table of contents" }),
|
|
119
|
-
usageFile: z.string().default("").meta({ description: "Workspace level usage file" }),
|
|
120
|
-
usageHeading: z.string().default("Usage").meta({ description: "Markdown heading used to generate usage example" }),
|
|
116
|
+
tocHeading: z.string().trim().default("Table of contents").meta({ description: "Markdown heading used to generate table of contents" }),
|
|
117
|
+
usageFile: z.string().trim().default("").meta({ description: "Workspace level usage file" }),
|
|
118
|
+
usageHeading: z.string().trim().default("Usage").meta({ description: "Markdown heading used to generate usage example" }),
|
|
121
119
|
verbose: z.boolean().default(false).meta({
|
|
122
120
|
alias: "v",
|
|
123
121
|
description: "whether or not to display verbose logging"
|
|
124
122
|
})
|
|
125
|
-
});
|
|
126
|
-
const configSchema = _configSchema.optional();
|
|
127
|
-
|
|
123
|
+
}).optional();
|
|
128
124
|
//#endregion
|
|
129
|
-
//#region src/
|
|
125
|
+
//#region src/arguments.ts
|
|
130
126
|
const complexOptions = [
|
|
131
127
|
"affectedRegexes",
|
|
132
128
|
"collapseHeadings",
|
|
133
129
|
"headings",
|
|
134
130
|
"templates"
|
|
135
131
|
];
|
|
136
|
-
const
|
|
132
|
+
const arguments_ = {
|
|
137
133
|
...zodToYargs(),
|
|
138
134
|
changes: {
|
|
139
135
|
alias: "g",
|
|
@@ -153,10 +149,10 @@ const args = {
|
|
|
153
149
|
type: "string"
|
|
154
150
|
}
|
|
155
151
|
};
|
|
156
|
-
async function
|
|
157
|
-
const yargsInstance = yargs(hideBin(process.argv)).options(
|
|
152
|
+
async function parseArguments() {
|
|
153
|
+
const yargsInstance = yargs(hideBin(process.argv)).options(arguments_).help("h").alias("h", "help").epilogue(`--> @stephansama open-source ${(/* @__PURE__ */ new Date()).getFullYear()}`);
|
|
158
154
|
const parsed = await yargsInstance.wrap(yargsInstance.terminalWidth()).parse();
|
|
159
|
-
if (parsed.verbose)
|
|
155
|
+
if (parsed.verbose) enable("autoreadme*");
|
|
160
156
|
return parsed;
|
|
161
157
|
}
|
|
162
158
|
function zodToYargs() {
|
|
@@ -179,25 +175,12 @@ function zodToYargs() {
|
|
|
179
175
|
});
|
|
180
176
|
return Object.fromEntries(entries);
|
|
181
177
|
}
|
|
182
|
-
|
|
183
178
|
//#endregion
|
|
184
179
|
//#region src/log.ts
|
|
185
|
-
const
|
|
186
|
-
const
|
|
187
|
-
const
|
|
188
|
-
|
|
189
|
-
const [first, ...remaining] = rest;
|
|
190
|
-
error(`${first} %O`, ...remaining);
|
|
191
|
-
}
|
|
192
|
-
function INFO(...rest) {
|
|
193
|
-
const [first, ...remaining] = rest;
|
|
194
|
-
info(`${first} %O`, ...remaining);
|
|
195
|
-
}
|
|
196
|
-
function WARN(...rest) {
|
|
197
|
-
const [first, ...remaining] = rest;
|
|
198
|
-
warn(`${first} %O`, ...remaining);
|
|
199
|
-
}
|
|
200
|
-
|
|
180
|
+
const debug = createDebug("autoreadme", { useColors: true });
|
|
181
|
+
const ERROR = debug.extend("error");
|
|
182
|
+
const INFO = debug.extend("info");
|
|
183
|
+
const WARN = debug.extend("warn");
|
|
201
184
|
//#endregion
|
|
202
185
|
//#region src/comment.ts
|
|
203
186
|
const SEPARATOR = "-";
|
|
@@ -214,7 +197,7 @@ function parseComment(comment) {
|
|
|
214
197
|
});
|
|
215
198
|
const languageInput = third ? first : void 0;
|
|
216
199
|
const actionInput = third ? second : first;
|
|
217
|
-
const formatInput = third
|
|
200
|
+
const formatInput = third || second;
|
|
218
201
|
const language = languageSchema.parse(languageInput);
|
|
219
202
|
const parsed = {
|
|
220
203
|
action: actionsSchema.parse(actionInput),
|
|
@@ -228,8 +211,9 @@ function parseComment(comment) {
|
|
|
228
211
|
}
|
|
229
212
|
const startComment = "<!--";
|
|
230
213
|
const endComment = "-->";
|
|
214
|
+
const commentRegex = /start|end/;
|
|
231
215
|
function trimComment(comment) {
|
|
232
|
-
return comment.replace(startComment, "").replace(
|
|
216
|
+
return comment.replace(startComment, "").replace(commentRegex, "").replace(endComment, "").trim();
|
|
233
217
|
}
|
|
234
218
|
function getComment(comment) {
|
|
235
219
|
if (!isComment(comment.value)) return false;
|
|
@@ -239,29 +223,28 @@ function getComment(comment) {
|
|
|
239
223
|
function isComment(comment) {
|
|
240
224
|
return comment.startsWith(startComment) && comment.endsWith(endComment);
|
|
241
225
|
}
|
|
242
|
-
|
|
243
226
|
//#endregion
|
|
244
227
|
//#region src/config.ts
|
|
245
228
|
const moduleName = "autoreadme";
|
|
246
229
|
const searchPlaces = getSearchPlaces();
|
|
247
230
|
const loaders = { [".toml"]: loadToml };
|
|
248
|
-
async function loadConfig(
|
|
249
|
-
const
|
|
231
|
+
async function loadConfig(arguments_) {
|
|
232
|
+
const options = {
|
|
250
233
|
loaders,
|
|
251
234
|
searchPlaces
|
|
252
235
|
};
|
|
253
|
-
if (
|
|
254
|
-
const search = await cosmiconfig(moduleName,
|
|
255
|
-
if (
|
|
256
|
-
WARN(`no config file found`, args$1.config ? " at location: " + args$1.config : "");
|
|
257
|
-
INFO("using default configuration");
|
|
258
|
-
} else {
|
|
236
|
+
if (arguments_.config) options.searchPlaces = [arguments_.config];
|
|
237
|
+
const search = await cosmiconfig(moduleName, options).search();
|
|
238
|
+
if (search) {
|
|
259
239
|
INFO("found configuration file at: ", search.filepath);
|
|
260
240
|
INFO("loaded cosmiconfig", search.config);
|
|
241
|
+
} else {
|
|
242
|
+
WARN(`no config file found`, arguments_.config ? " at location: " + arguments_.config : "");
|
|
243
|
+
INFO("using default configuration");
|
|
261
244
|
}
|
|
262
|
-
|
|
263
|
-
INFO("merging config with args",
|
|
264
|
-
return configSchema.parse(deepmerge(search?.config || {},
|
|
245
|
+
arguments_ = removeFalsy(arguments_);
|
|
246
|
+
INFO("merging config with args", arguments_);
|
|
247
|
+
return configSchema.parse(deepmerge(search?.config || {}, arguments_, { arrayMerge: (_, sourceArray) => sourceArray }));
|
|
265
248
|
}
|
|
266
249
|
function loadToml(_filepath, content) {
|
|
267
250
|
return toml.parse(content);
|
|
@@ -278,14 +261,13 @@ function getSearchPlaces() {
|
|
|
278
261
|
`.config/.${moduleName}rc.yml`
|
|
279
262
|
];
|
|
280
263
|
}
|
|
281
|
-
function removeFalsy(
|
|
282
|
-
return Object.fromEntries(Object.entries(
|
|
264
|
+
function removeFalsy(object) {
|
|
265
|
+
return Object.fromEntries(Object.entries(object).map(([k, v]) => v ? [k, v] : false).filter(Boolean));
|
|
283
266
|
}
|
|
284
|
-
|
|
285
267
|
//#endregion
|
|
286
|
-
//#region src/
|
|
268
|
+
//#region src/utilities.ts
|
|
287
269
|
const sh = String.raw;
|
|
288
|
-
const
|
|
270
|
+
const options = { encoding: "utf8" };
|
|
289
271
|
const ignore = ["**/node_modules/**"];
|
|
290
272
|
const matches = [
|
|
291
273
|
/.*README\.md$/gi,
|
|
@@ -298,21 +280,23 @@ async function fileExists(file) {
|
|
|
298
280
|
return await fsp.access(file).then(() => true).catch(() => false);
|
|
299
281
|
}
|
|
300
282
|
function findAffectedMarkdowns(root, config) {
|
|
301
|
-
const affected = cp.execSync(sh`git diff --cached --name-only --diff-filter=MACT`,
|
|
302
|
-
if (
|
|
283
|
+
const affected = cp.execSync(sh`git diff --cached --name-only --diff-filter=MACT`, options).trim().split("\n").filter((item) => !!item);
|
|
284
|
+
if (affected.length === 0) ERROR("no staged files found");
|
|
303
285
|
if (config.affectedRegexes?.length) INFO("adding the following expressions: ", config.affectedRegexes);
|
|
304
286
|
const allMatches = [...matches, ...config.affectedRegexes?.map((r) => new RegExp(r)) || []];
|
|
305
287
|
INFO("Checking affected files against regexes", affected, allMatches);
|
|
306
288
|
const eligible = affected.filter((a) => allMatches.some((m) => a.match(m)));
|
|
307
289
|
INFO("Found the following eligible affected files", eligible);
|
|
308
|
-
const md = eligible.map((
|
|
309
|
-
|
|
310
|
-
|
|
290
|
+
const md = eligible.map((current) => {
|
|
291
|
+
return findNearestReadme(root, path.resolve(current));
|
|
292
|
+
});
|
|
293
|
+
const rootMd = path.join(root, "README.md");
|
|
294
|
+
const dedupe = [...new Set(md), rootMd].filter((item) => !!item);
|
|
311
295
|
INFO("Found the following readmes", dedupe);
|
|
312
296
|
return dedupe;
|
|
313
297
|
}
|
|
314
298
|
function getGitRoot() {
|
|
315
|
-
const root = cp.execSync(sh`git rev-parse --show-toplevel`,
|
|
299
|
+
const root = cp.execSync(sh`git rev-parse --show-toplevel`, options).trim();
|
|
316
300
|
if (!root) throw new Error("must be ran within a git directory.");
|
|
317
301
|
INFO("found git root at location: ", root);
|
|
318
302
|
return root;
|
|
@@ -321,33 +305,31 @@ async function getMarkdownPaths(cwd, config) {
|
|
|
321
305
|
return (await glob(`**/${config?.onlyReadmes ? "README" : "*"}.md`, {
|
|
322
306
|
cwd,
|
|
323
307
|
ignore
|
|
324
|
-
})).map((readme) => path
|
|
308
|
+
})).map((readme) => path.resolve(cwd, readme));
|
|
325
309
|
}
|
|
326
310
|
async function getPrettierPaths(paths) {
|
|
327
311
|
return await Promise.all(paths.map(async (file) => {
|
|
328
312
|
if (!(await fsp.lstat(file)).isSymbolicLink()) return file;
|
|
329
313
|
const symlink = await fsp.readlink(file);
|
|
330
|
-
return path
|
|
314
|
+
return path.join(path.dirname(file), symlink);
|
|
331
315
|
}));
|
|
332
316
|
}
|
|
333
317
|
function findNearestReadme(gitRoot, inputFile, maxRotations = 15) {
|
|
334
|
-
let
|
|
318
|
+
let dirname = path.dirname(inputFile);
|
|
335
319
|
let rotations = 0;
|
|
336
320
|
while (true) {
|
|
337
|
-
const option = path
|
|
321
|
+
const option = path.join(dirname, "README.md");
|
|
338
322
|
if (fs.existsSync(option)) return option;
|
|
339
|
-
const parent = path
|
|
340
|
-
if (parent ===
|
|
341
|
-
|
|
323
|
+
const parent = path.dirname(dirname);
|
|
324
|
+
if (parent === dirname || dirname === gitRoot || ++rotations > maxRotations) break;
|
|
325
|
+
dirname = parent;
|
|
342
326
|
}
|
|
343
|
-
return null;
|
|
344
327
|
}
|
|
345
|
-
|
|
346
328
|
//#endregion
|
|
347
329
|
//#region src/data.ts
|
|
348
330
|
function createFindParameter(parameterList) {
|
|
349
331
|
return function(parameterName) {
|
|
350
|
-
return parameterList?.find((p) => p.startsWith(parameterName))?.replace(parameterName + "=", "")?.
|
|
332
|
+
return parameterList?.find((p) => p.startsWith(parameterName))?.replace(parameterName + "=", "")?.replaceAll("\"", "")?.replaceAll("_", " ");
|
|
351
333
|
};
|
|
352
334
|
}
|
|
353
335
|
async function loadActionData(actions, file, root) {
|
|
@@ -356,7 +338,7 @@ async function loadActionData(actions, file, root) {
|
|
|
356
338
|
const find = createFindParameter(action.parameters);
|
|
357
339
|
switch (action.action) {
|
|
358
340
|
case "ACTION": {
|
|
359
|
-
const actionYaml = await loadActionYaml(path
|
|
341
|
+
const actionYaml = await loadActionYaml(path.dirname(file));
|
|
360
342
|
return {
|
|
361
343
|
action: action.action,
|
|
362
344
|
actionYaml,
|
|
@@ -365,7 +347,7 @@ async function loadActionData(actions, file, root) {
|
|
|
365
347
|
}
|
|
366
348
|
case "PKG": {
|
|
367
349
|
const inputPath = find("path");
|
|
368
|
-
const pkgJson = await readPackageJSON(inputPath ? path
|
|
350
|
+
const pkgJson = await readPackageJSON(inputPath ? path.resolve(path.dirname(file), inputPath) : path.dirname(file));
|
|
369
351
|
return {
|
|
370
352
|
action: action.action,
|
|
371
353
|
parameters: action.parameters,
|
|
@@ -378,7 +360,7 @@ async function loadActionData(actions, file, root) {
|
|
|
378
360
|
};
|
|
379
361
|
case "WORKSPACE": {
|
|
380
362
|
const workspaces = await getPackages(process.cwd());
|
|
381
|
-
const pnpmPath = path
|
|
363
|
+
const pnpmPath = path.resolve(root, "pnpm-workspace.yaml");
|
|
382
364
|
const isPnpm = fs.existsSync(pnpmPath);
|
|
383
365
|
return {
|
|
384
366
|
action: action.action,
|
|
@@ -392,11 +374,11 @@ async function loadActionData(actions, file, root) {
|
|
|
392
374
|
if (action.format === "LIST") throw new Error("cannot display zod in list format");
|
|
393
375
|
const inputPath = find("path");
|
|
394
376
|
if (!inputPath) {
|
|
395
|
-
const error
|
|
396
|
-
throw new Error(error
|
|
377
|
+
const error = `no path found for zod table at markdown file ${file}`;
|
|
378
|
+
throw new Error(error);
|
|
397
379
|
}
|
|
398
380
|
const body = await zod2md({
|
|
399
|
-
entry: path
|
|
381
|
+
entry: path.resolve(path.dirname(file), inputPath),
|
|
400
382
|
title: find("title") || "Zod Schema"
|
|
401
383
|
});
|
|
402
384
|
return {
|
|
@@ -409,18 +391,17 @@ async function loadActionData(actions, file, root) {
|
|
|
409
391
|
}
|
|
410
392
|
}));
|
|
411
393
|
}
|
|
412
|
-
async function loadActionYaml(
|
|
413
|
-
const actionYmlPath = path
|
|
414
|
-
const actionYamlPath = path
|
|
394
|
+
async function loadActionYaml(baseDirectory) {
|
|
395
|
+
const actionYmlPath = path.resolve(baseDirectory, "action.yml");
|
|
396
|
+
const actionYamlPath = path.resolve(baseDirectory, "action.yaml");
|
|
415
397
|
const actualPath = await fileExists(actionYamlPath) && actionYamlPath || await fileExists(actionYmlPath) && actionYmlPath;
|
|
416
398
|
if (!actualPath) {
|
|
417
|
-
const error
|
|
418
|
-
throw new Error(error
|
|
399
|
+
const error = `no yaml file found at locations: ${[actionYmlPath, actionYamlPath].join(",")}`;
|
|
400
|
+
throw new Error(error);
|
|
419
401
|
}
|
|
420
402
|
const actionFile = await fsp.readFile(actualPath, { encoding: "utf8" });
|
|
421
403
|
return yaml.parse(actionFile);
|
|
422
404
|
}
|
|
423
|
-
|
|
424
405
|
//#endregion
|
|
425
406
|
//#region src/plugin.ts
|
|
426
407
|
function createHeading(headings, disableEmojis = false, emojis = defaultTemplates.emojis) {
|
|
@@ -448,8 +429,8 @@ const autoReadmeRemarkPlugin = (config, data) => (tree) => {
|
|
|
448
429
|
const heading = `### ${config.disableEmojis ? "" : "🧰"} actions`;
|
|
449
430
|
if (options.format === "LIST") return [
|
|
450
431
|
start,
|
|
451
|
-
fromMarkdown(`${heading}\n` + Object.entries(inputs).
|
|
452
|
-
return `- ${wrapRequired(value
|
|
432
|
+
fromMarkdown(`${heading}\n` + Object.entries(inputs).toSorted((a) => a[1].required ? -1 : 1).map(([key, value]) => {
|
|
433
|
+
return `- ${wrapRequired(value.required, key)}: (default: ${value.default})\n\n${value.description}`;
|
|
453
434
|
}).join("\n")),
|
|
454
435
|
end
|
|
455
436
|
];
|
|
@@ -459,7 +440,7 @@ const autoReadmeRemarkPlugin = (config, data) => (tree) => {
|
|
|
459
440
|
fromMarkdown([
|
|
460
441
|
heading,
|
|
461
442
|
"",
|
|
462
|
-
markdownTable([createHeading(headings, config.disableEmojis, config.templates?.emojis), ...Object.entries(inputs).map(([k, v]) => headings.map((heading
|
|
443
|
+
markdownTable([createHeading(headings, config.disableEmojis, config.templates?.emojis), ...Object.entries(inputs).map(([k, v]) => headings.map((heading) => v[heading] || k).map(String))])
|
|
463
444
|
].join("\n")),
|
|
464
445
|
end
|
|
465
446
|
];
|
|
@@ -472,9 +453,9 @@ const autoReadmeRemarkPlugin = (config, data) => (tree) => {
|
|
|
472
453
|
const packages = workspace?.workspaces?.packages || [];
|
|
473
454
|
const headings = config.headings?.WORKSPACE?.length && config.headings?.WORKSPACE || defaultTableHeadings.WORKSPACE;
|
|
474
455
|
if (comment && comment.format === "LIST") {}
|
|
475
|
-
const table = markdownTable([createHeading(headings, config.disableEmojis, config.templates?.emojis), ...packages.filter((pkg) => config.onlyShowPublicPackages ? !pkg.packageJson.private : true).map((pkg) => {
|
|
456
|
+
const table = markdownTable([createHeading(headings, config.disableEmojis, config.templates?.emojis) || [], ...packages.filter((pkg) => config.onlyShowPublicPackages ? !pkg.packageJson.private : true).map((pkg) => {
|
|
476
457
|
const { name } = pkg.packageJson;
|
|
477
|
-
return headings
|
|
458
|
+
return headings?.map((heading) => {
|
|
478
459
|
if (heading === "name") return `[${config.removeScope ? name.replace(config.removeScope, "") : name}](${path.relative(process.cwd(), path.resolve(pkg.dir, "README.md"))})`;
|
|
479
460
|
if (heading === "version") return ` })})`;
|
|
480
461
|
if (heading === "downloads") return `})`;
|
|
@@ -503,13 +484,13 @@ const autoReadmeRemarkPlugin = (config, data) => (tree) => {
|
|
|
503
484
|
fromMarkdown(""),
|
|
504
485
|
end
|
|
505
486
|
];
|
|
506
|
-
function mapDependencies(
|
|
487
|
+
function mapDependencies(isDevelopment) {
|
|
507
488
|
return function([name, version]) {
|
|
508
489
|
const url = templates.registryUrl({ name });
|
|
509
490
|
return headings.map((key) => {
|
|
510
491
|
if (key === "devDependency") {
|
|
511
|
-
if (config.disableEmojis) return `\`${
|
|
512
|
-
return `${
|
|
492
|
+
if (config.disableEmojis) return `\`${isDevelopment}\``;
|
|
493
|
+
return `${isDevelopment ? "⌨️" : "👥"}`;
|
|
513
494
|
}
|
|
514
495
|
if (key === "name") return `[${name}](${url})`;
|
|
515
496
|
if (key === "version") {
|
|
@@ -547,7 +528,6 @@ function loadTemplates(templates) {
|
|
|
547
528
|
return [key, Handlebars.compile(value)];
|
|
548
529
|
}));
|
|
549
530
|
}
|
|
550
|
-
|
|
551
531
|
//#endregion
|
|
552
532
|
//#region src/pipeline.ts
|
|
553
533
|
async function parse(file, filepath, root, config, data) {
|
|
@@ -555,10 +535,10 @@ async function parse(file, filepath, root, config, data) {
|
|
|
555
535
|
const usage = data.find((d) => d.action === "USAGE");
|
|
556
536
|
if (usage?.action === "USAGE" || config.enableUsage) {
|
|
557
537
|
const examplePath = createFindParameter(usage?.parameters || [])("path");
|
|
558
|
-
const dirname = path
|
|
559
|
-
const resolvePath = examplePath && path
|
|
560
|
-
const relativeProjectPath = config.usageFile && path
|
|
561
|
-
const example = examplePath && resolvePath && path
|
|
538
|
+
const dirname = path.dirname(filepath);
|
|
539
|
+
const resolvePath = examplePath && path.resolve(dirname, examplePath);
|
|
540
|
+
const relativeProjectPath = config.usageFile && path.relative(root, path.resolve(dirname, config.usageFile));
|
|
541
|
+
const example = examplePath && resolvePath && path.relative(root, resolvePath) || relativeProjectPath || void 0;
|
|
562
542
|
if (example && await fileExists(example)) {
|
|
563
543
|
INFO("generating usage section");
|
|
564
544
|
pipeline.use(remarkUsage, {
|
|
@@ -576,58 +556,57 @@ async function parse(file, filepath, root, config, data) {
|
|
|
576
556
|
pipeline.use(remarkCollapse, { test: {
|
|
577
557
|
ignoreFinalDefinitions: true,
|
|
578
558
|
test: (value, _) => {
|
|
579
|
-
return headings.some((
|
|
559
|
+
return headings.some((item) => value.trim() === item?.trim());
|
|
580
560
|
}
|
|
581
561
|
} });
|
|
582
562
|
}
|
|
583
563
|
const vfile = new VFile({
|
|
584
|
-
path: path
|
|
564
|
+
path: path.resolve(filepath),
|
|
585
565
|
value: file
|
|
586
566
|
});
|
|
587
567
|
return (await pipeline.process(vfile)).toString();
|
|
588
568
|
}
|
|
589
|
-
|
|
590
569
|
//#endregion
|
|
591
570
|
//#region src/index.ts
|
|
592
571
|
async function run() {
|
|
593
|
-
const
|
|
594
|
-
const config = await loadConfig(
|
|
572
|
+
const arguments_ = await parseArguments();
|
|
573
|
+
const config = await loadConfig(arguments_) || {};
|
|
595
574
|
INFO("Loaded the following configuration:", config);
|
|
596
575
|
const root = getGitRoot();
|
|
597
|
-
const isAffected =
|
|
598
|
-
INFO(`Loading ${
|
|
576
|
+
const isAffected = arguments_.changes && "affected";
|
|
577
|
+
INFO(`Loading ${isAffected ? "affected " : "all "}files`);
|
|
599
578
|
const paths = isAffected ? findAffectedMarkdowns(root, config) : await getMarkdownPaths(root, config);
|
|
600
579
|
INFO("Loaded the following files:", paths.join("\n"));
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
await Promise.all(paths.map(async (path
|
|
605
|
-
const file = await fsp.readFile(path
|
|
606
|
-
const actions = (()
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
if (!actions.length) {
|
|
610
|
-
WARN(`no action comments found in`, path$2);
|
|
580
|
+
if (paths.length === 0) return ERROR(`no ${isAffected} readmes found to update`);
|
|
581
|
+
const spinner = !arguments_.verbose && makeSpinner();
|
|
582
|
+
if (spinner) spinner.start();
|
|
583
|
+
await Promise.all(paths.filter((path) => !!path).map(async (path) => {
|
|
584
|
+
const file = await fsp.readFile(path, { encoding: "utf8" });
|
|
585
|
+
const actions = loadAstComments(fromMarkdown(file));
|
|
586
|
+
if (actions.length === 0) {
|
|
587
|
+
WARN(`no action comments found in`, path);
|
|
611
588
|
if (!config.enableUsage || !config.enableToc) return ERROR("no action or plugins found");
|
|
612
|
-
else INFO("plugins enabled. continuing parsing", path
|
|
589
|
+
else INFO("plugins enabled. continuing parsing", path);
|
|
613
590
|
}
|
|
614
|
-
const data = await loadActionData(actions, path
|
|
591
|
+
const data = await loadActionData(actions, path, root);
|
|
615
592
|
INFO("Loaded comment action data", data);
|
|
616
|
-
const content = await parse(file, path
|
|
617
|
-
await fsp.writeFile(path
|
|
593
|
+
const content = await parse(file, path, root, config, data);
|
|
594
|
+
await fsp.writeFile(path, content);
|
|
618
595
|
}));
|
|
619
|
-
const
|
|
596
|
+
const options = { stdio: "inherit" };
|
|
620
597
|
if (config.enablePrettier) {
|
|
621
598
|
INFO("formatting with prettier");
|
|
622
599
|
const prettierPaths = await getPrettierPaths(paths);
|
|
623
|
-
cp.execFileSync("prettier", ["--write", ...prettierPaths],
|
|
600
|
+
cp.execFileSync("prettier", ["--write", ...prettierPaths], options);
|
|
624
601
|
}
|
|
625
602
|
if (isAffected) {
|
|
626
603
|
INFO("adding affected files to git stage");
|
|
627
|
-
cp.execFileSync("git", ["add", ...paths],
|
|
604
|
+
cp.execFileSync("git", ["add", ...paths], options);
|
|
628
605
|
}
|
|
629
606
|
if (spinner) spinner.stop();
|
|
630
607
|
}
|
|
631
|
-
|
|
608
|
+
function makeSpinner() {
|
|
609
|
+
return new Spinner("Updating readme...", { colors: { spinner: "red" } });
|
|
610
|
+
}
|
|
632
611
|
//#endregion
|
|
633
|
-
export { run };
|
|
612
|
+
export { run };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@stephansama/auto-readme",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.9",
|
|
4
4
|
"description": "Generate lists and tables for your README automagically based on your repository and comments",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"auto",
|
|
@@ -24,48 +24,42 @@
|
|
|
24
24
|
"email": "stephanrandle.dev@gmail.com",
|
|
25
25
|
"url": "https://stephansama.info"
|
|
26
26
|
},
|
|
27
|
+
"sideEffects": false,
|
|
27
28
|
"type": "module",
|
|
28
29
|
"exports": {
|
|
29
30
|
".": {
|
|
30
|
-
"import":
|
|
31
|
-
|
|
32
|
-
"default": "./config/schema.js"
|
|
33
|
-
},
|
|
34
|
-
"require": {
|
|
35
|
-
"types": "./config/schema.d.cts",
|
|
36
|
-
"default": "./config/schema.cjs"
|
|
37
|
-
}
|
|
31
|
+
"import": "./config/schema.mjs",
|
|
32
|
+
"require": "./config/schema.cjs"
|
|
38
33
|
},
|
|
39
|
-
"./schema.json": "./config/schema.json",
|
|
40
34
|
"./package.json": "./package.json"
|
|
41
35
|
},
|
|
42
|
-
"main": "./config/schema.
|
|
43
|
-
"
|
|
36
|
+
"main": "./config/schema.cjs",
|
|
37
|
+
"module": "./config/schema.mjs",
|
|
38
|
+
"types": "./config/schema.d.cts",
|
|
44
39
|
"bin": "./cli.mjs",
|
|
45
40
|
"files": [
|
|
46
41
|
"./dist",
|
|
47
|
-
"./config"
|
|
48
|
-
"./cli.mjs"
|
|
42
|
+
"./config"
|
|
49
43
|
],
|
|
50
44
|
"dependencies": {
|
|
51
|
-
"@
|
|
52
|
-
"@manypkg/get-packages": "^3.1.0",
|
|
45
|
+
"@manypkg/get-packages": "3.1.0",
|
|
53
46
|
"cosmiconfig": "9.0.0",
|
|
54
|
-
"debug": "^4.4.3",
|
|
55
47
|
"deepmerge": "4.3.1",
|
|
56
|
-
"
|
|
57
|
-
"handlebars": "4.7.8",
|
|
48
|
+
"handlebars": "4.7.9",
|
|
58
49
|
"markdown-table": "^3.0.4",
|
|
50
|
+
"mdast": "3.0.0",
|
|
59
51
|
"mdast-comment-marker": "^3.0.0",
|
|
60
52
|
"mdast-util-from-markdown": "^2.0.2",
|
|
61
53
|
"mdast-zone": "github:stephansama/mdast-zone#1c5b08cd97240debeed4c9c6afad49df5877a132",
|
|
62
|
-
"
|
|
54
|
+
"obug": "2.1.1",
|
|
63
55
|
"pkg-types": "^2.3.0",
|
|
64
56
|
"remark": "15.0.1",
|
|
65
57
|
"remark-code-import": "^1.2.0",
|
|
66
58
|
"remark-collapse": "^0.1.2",
|
|
67
59
|
"remark-toc": "^9.0.0",
|
|
68
60
|
"remark-usage": "^11.0.1",
|
|
61
|
+
"smol-toml": "1.6.1",
|
|
62
|
+
"tinyglobby": "0.2.16",
|
|
69
63
|
"vfile": "^6.0.3",
|
|
70
64
|
"yaml": "^2.8.2",
|
|
71
65
|
"yargs": "18.0.0",
|
|
@@ -73,14 +67,16 @@
|
|
|
73
67
|
"zod2md": "^0.2.5"
|
|
74
68
|
},
|
|
75
69
|
"devDependencies": {
|
|
76
|
-
"@types/debug": "4.1.12",
|
|
77
70
|
"@types/mdast": "4.0.4",
|
|
78
71
|
"@types/vfile": "4.0.0",
|
|
79
72
|
"@types/yargs": "17.0.35",
|
|
80
|
-
"
|
|
81
|
-
"tsdown": "0.
|
|
73
|
+
"picospinner": "3.0.0",
|
|
74
|
+
"tsdown": "0.21.10",
|
|
82
75
|
"unified": "11.0.5"
|
|
83
76
|
},
|
|
77
|
+
"engines": {
|
|
78
|
+
"node": ">=24"
|
|
79
|
+
},
|
|
84
80
|
"publishConfig": {
|
|
85
81
|
"access": "public",
|
|
86
82
|
"provenance": true
|
|
@@ -89,6 +85,7 @@
|
|
|
89
85
|
"build": "node build.mjs",
|
|
90
86
|
"postbuild": "publint",
|
|
91
87
|
"dev": "node --watch-path=./src build.mjs",
|
|
92
|
-
"lint": "eslint ./src/ --pass-on-no-patterns --no-error-on-unmatched-pattern"
|
|
88
|
+
"lint": "eslint ./src/ --pass-on-no-patterns --no-error-on-unmatched-pattern",
|
|
89
|
+
"lint:fix": "eslint ./src/ --pass-on-no-patterns --no-error-on-unmatched-pattern --fix"
|
|
93
90
|
}
|
|
94
91
|
}
|
|
File without changes
|
|
File without changes
|