@stephansama/auto-readme 0.1.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/LICENSE +21 -0
- package/README.md +230 -0
- package/cli.mjs +5 -0
- package/config/schema.cjs +135 -0
- package/config/schema.cjs.map +1 -0
- package/config/schema.d.cts +167 -0
- package/config/schema.d.ts +167 -0
- package/config/schema.js +102 -0
- package/config/schema.js.map +1 -0
- package/config/schema.json +1 -0
- package/config/schema.yaml +182 -0
- package/dist/index.cjs +676 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.js +641 -0
- package/dist/index.js.map +1 -0
- package/package.json +88 -0
package/dist/index.cjs
ADDED
|
@@ -0,0 +1,676 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __create = Object.create;
|
|
3
|
+
var __defProp = Object.defineProperty;
|
|
4
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
5
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
6
|
+
var __getProtoOf = Object.getPrototypeOf;
|
|
7
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
8
|
+
var __export = (target, all) => {
|
|
9
|
+
for (var name in all)
|
|
10
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
11
|
+
};
|
|
12
|
+
var __copyProps = (to, from, except, desc) => {
|
|
13
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
14
|
+
for (let key of __getOwnPropNames(from))
|
|
15
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
16
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
17
|
+
}
|
|
18
|
+
return to;
|
|
19
|
+
};
|
|
20
|
+
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
|
|
21
|
+
// If the importer is in node compatibility mode or this is not an ESM
|
|
22
|
+
// file that has been converted to a CommonJS file using a Babel-
|
|
23
|
+
// compatible transform (i.e. "__esModule" has not been set), then set
|
|
24
|
+
// "default" to the CommonJS "module.exports" for node compatibility.
|
|
25
|
+
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
|
|
26
|
+
mod
|
|
27
|
+
));
|
|
28
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
29
|
+
|
|
30
|
+
// src/index.ts
|
|
31
|
+
var index_exports = {};
|
|
32
|
+
__export(index_exports, {
|
|
33
|
+
run: () => run
|
|
34
|
+
});
|
|
35
|
+
module.exports = __toCommonJS(index_exports);
|
|
36
|
+
var import_mdast_util_from_markdown2 = require("mdast-util-from-markdown");
|
|
37
|
+
var cp2 = __toESM(require("child_process"), 1);
|
|
38
|
+
var fsp3 = __toESM(require("fs/promises"), 1);
|
|
39
|
+
var import_ora = __toESM(require("ora"), 1);
|
|
40
|
+
|
|
41
|
+
// src/args.ts
|
|
42
|
+
var import_yargs = __toESM(require("yargs"), 1);
|
|
43
|
+
var import_helpers = require("yargs/helpers");
|
|
44
|
+
var import_zod2 = __toESM(require("zod"), 1);
|
|
45
|
+
|
|
46
|
+
// src/log.ts
|
|
47
|
+
var import_chalk = __toESM(require("chalk"), 1);
|
|
48
|
+
var verbosity = 0;
|
|
49
|
+
function ERROR(...rest) {
|
|
50
|
+
const [first, ...remaining] = rest;
|
|
51
|
+
console.error(import_chalk.default.red(first), ...remaining);
|
|
52
|
+
}
|
|
53
|
+
function INFO(...rest) {
|
|
54
|
+
if (verbosity < 1) return;
|
|
55
|
+
const [first, ...remaining] = rest;
|
|
56
|
+
console.info(import_chalk.default.blue(first), ...remaining);
|
|
57
|
+
}
|
|
58
|
+
function setVerbosity(input) {
|
|
59
|
+
verbosity = input;
|
|
60
|
+
}
|
|
61
|
+
function WARN(...rest) {
|
|
62
|
+
if (verbosity < 1) return;
|
|
63
|
+
const [first, ...remaining] = rest;
|
|
64
|
+
console.warn(import_chalk.default.yellow(first), ...remaining);
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
// src/schema.js
|
|
68
|
+
var import_zod = require("zod");
|
|
69
|
+
var actionsSchema = import_zod.z.enum(["ACTION", "PKG", "USAGE", "WORKSPACE", "ZOD"]).describe("Comment action options");
|
|
70
|
+
var formatsSchema = import_zod.z.enum(["LIST", "TABLE"]).default("TABLE").optional();
|
|
71
|
+
var languageSchema = import_zod.z.enum(["JS", "RS"]).optional().default("JS");
|
|
72
|
+
var headingsSchema = import_zod.z.enum([
|
|
73
|
+
"default",
|
|
74
|
+
"description",
|
|
75
|
+
"devDependency",
|
|
76
|
+
"downloads",
|
|
77
|
+
"name",
|
|
78
|
+
"private",
|
|
79
|
+
"required",
|
|
80
|
+
"version"
|
|
81
|
+
]).describe("Table heading options");
|
|
82
|
+
var tableHeadingsSchema = import_zod.z.record(actionsSchema, headingsSchema.array().optional()).optional().describe("Table heading action configuration").default({
|
|
83
|
+
ACTION: ["name", "required", "default", "description"],
|
|
84
|
+
PKG: ["name", "version", "devDependency"],
|
|
85
|
+
WORKSPACE: ["name", "version", "downloads", "description"],
|
|
86
|
+
ZOD: []
|
|
87
|
+
});
|
|
88
|
+
var templatesSchema = import_zod.z.object({
|
|
89
|
+
downloadImage: import_zod.z.string().optional().default("https://img.shields.io/npm/dw/{{name}}?labelColor=211F1F"),
|
|
90
|
+
emojis: import_zod.z.record(headingsSchema, import_zod.z.string()).optional().describe("Table heading emojis used when enabled").default({
|
|
91
|
+
default: "\u2699\uFE0F",
|
|
92
|
+
description: "\u{1F4DD}",
|
|
93
|
+
devDependency: "\u{1F4BB}",
|
|
94
|
+
downloads: "\u{1F4E5}",
|
|
95
|
+
name: "\u{1F3F7}\uFE0F",
|
|
96
|
+
private: "\u{1F512}",
|
|
97
|
+
required: "",
|
|
98
|
+
version: ""
|
|
99
|
+
}),
|
|
100
|
+
registryUrl: import_zod.z.string().optional().default("https://www.npmjs.com/package/{{name}}"),
|
|
101
|
+
versionImage: import_zod.z.string().optional().default(
|
|
102
|
+
"https://img.shields.io/npm/v/{{uri_name}}?logo=npm&logoColor=red&color=211F1F&labelColor=211F1F"
|
|
103
|
+
)
|
|
104
|
+
});
|
|
105
|
+
var defaultTemplates = templatesSchema.parse({});
|
|
106
|
+
var defaultTableHeadings = tableHeadingsSchema.parse(void 0);
|
|
107
|
+
var _configSchema = import_zod.z.object({
|
|
108
|
+
affectedRegexes: import_zod.z.string().array().optional().default([]),
|
|
109
|
+
defaultLanguage: languageSchema.meta({
|
|
110
|
+
alias: "l",
|
|
111
|
+
description: "Default language to infer projects from"
|
|
112
|
+
}),
|
|
113
|
+
disableEmojis: import_zod.z.boolean().default(false).meta({
|
|
114
|
+
alias: "e",
|
|
115
|
+
description: "Whether or not to use emojis in markdown table headings"
|
|
116
|
+
}),
|
|
117
|
+
disableMarkdownHeadings: import_zod.z.boolean().default(false).meta({
|
|
118
|
+
description: "Whether or not to display markdown headings"
|
|
119
|
+
}),
|
|
120
|
+
enableToc: import_zod.z.boolean().default(false).meta({
|
|
121
|
+
alias: "t",
|
|
122
|
+
description: "generate table of contents for readmes"
|
|
123
|
+
}),
|
|
124
|
+
enableUsage: import_zod.z.boolean().optional().default(false).meta({
|
|
125
|
+
description: "Whether or not to enable usage plugin"
|
|
126
|
+
}),
|
|
127
|
+
headings: tableHeadingsSchema.optional().default(defaultTableHeadings).describe("List of headings for different table outputs"),
|
|
128
|
+
onlyReadmes: import_zod.z.boolean().default(true).meta({
|
|
129
|
+
alias: "r",
|
|
130
|
+
description: "Whether or not to only traverse readmes"
|
|
131
|
+
}),
|
|
132
|
+
onlyShowPublicPackages: import_zod.z.boolean().default(false).meta({
|
|
133
|
+
alias: "p",
|
|
134
|
+
description: "Only show public packages in workspaces"
|
|
135
|
+
}),
|
|
136
|
+
removeScope: import_zod.z.string().optional().default("").meta({
|
|
137
|
+
description: "Remove common workspace scope"
|
|
138
|
+
}),
|
|
139
|
+
templates: templatesSchema.optional().default(defaultTemplates).describe(
|
|
140
|
+
"Handlebars templates used to fuel list and table generation"
|
|
141
|
+
),
|
|
142
|
+
tocHeading: import_zod.z.string().optional().default("Table of contents").meta({
|
|
143
|
+
description: "Markdown heading used to generate table of contents"
|
|
144
|
+
}),
|
|
145
|
+
usageFile: import_zod.z.string().optional().default("").meta({
|
|
146
|
+
description: "Workspace level usage file"
|
|
147
|
+
}),
|
|
148
|
+
usageHeading: import_zod.z.string().optional().default("Usage").meta({
|
|
149
|
+
description: "Markdown heading used to generate usage example"
|
|
150
|
+
}),
|
|
151
|
+
verbose: import_zod.z.boolean().default(false).meta({
|
|
152
|
+
alias: "v",
|
|
153
|
+
description: "whether or not to display verbose logging"
|
|
154
|
+
})
|
|
155
|
+
});
|
|
156
|
+
var configSchema = _configSchema.optional();
|
|
157
|
+
|
|
158
|
+
// src/args.ts
|
|
159
|
+
var complexOptions = ["affectedRegexes", "templates", "headings"];
|
|
160
|
+
var args = {
|
|
161
|
+
...zodToYargs(),
|
|
162
|
+
changes: {
|
|
163
|
+
alias: "g",
|
|
164
|
+
default: false,
|
|
165
|
+
description: "Check only changed git files",
|
|
166
|
+
type: "boolean"
|
|
167
|
+
},
|
|
168
|
+
check: {
|
|
169
|
+
alias: "k",
|
|
170
|
+
default: false,
|
|
171
|
+
description: "Do not write to files. Only check for changes",
|
|
172
|
+
type: "boolean"
|
|
173
|
+
},
|
|
174
|
+
config: { alias: "c", description: "Path to config file", type: "string" }
|
|
175
|
+
};
|
|
176
|
+
async function parseArgs() {
|
|
177
|
+
const yargsInstance = (0, import_yargs.default)((0, import_helpers.hideBin)(process.argv)).options(args).help("h").alias("h", "help").epilogue(`--> @stephansama open-source ${(/* @__PURE__ */ new Date()).getFullYear()}`);
|
|
178
|
+
const parsed = await yargsInstance.wrap(yargsInstance.terminalWidth()).parse();
|
|
179
|
+
if (parsed.verbose) setVerbosity(1);
|
|
180
|
+
return parsed;
|
|
181
|
+
}
|
|
182
|
+
function zodToYargs() {
|
|
183
|
+
const { shape } = configSchema.unwrap();
|
|
184
|
+
const entries = Object.entries(shape).map(([key, value]) => {
|
|
185
|
+
if (complexOptions.includes(key)) return [];
|
|
186
|
+
if (value.def.innerType instanceof import_zod2.default.ZodObject) return [];
|
|
187
|
+
const meta = value.meta();
|
|
188
|
+
const { innerType } = value.def;
|
|
189
|
+
const isBoolean = innerType instanceof import_zod2.default.ZodBoolean;
|
|
190
|
+
const isNumber = innerType instanceof import_zod2.default.ZodNumber;
|
|
191
|
+
const isArray = innerType instanceof import_zod2.default.ZodArray;
|
|
192
|
+
const yargType = isArray && "array" || isNumber && "number" || isBoolean && "boolean" || "string";
|
|
193
|
+
const options = {
|
|
194
|
+
default: value.def.defaultValue,
|
|
195
|
+
type: yargType
|
|
196
|
+
};
|
|
197
|
+
if (meta?.alias) options.alias = meta.alias;
|
|
198
|
+
if (meta?.description) options.description = meta.description;
|
|
199
|
+
return [key, options];
|
|
200
|
+
});
|
|
201
|
+
return Object.fromEntries(entries);
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
// src/comment.ts
|
|
205
|
+
var SEPARATOR = "-";
|
|
206
|
+
function loadAstComments(root) {
|
|
207
|
+
return root.children.map((child) => child.type === "html" && getComment(child.value)).filter((f) => f !== false);
|
|
208
|
+
}
|
|
209
|
+
function parseComment(comment) {
|
|
210
|
+
const input = trimComment(comment);
|
|
211
|
+
const [type, ...parameters] = input.split(" ");
|
|
212
|
+
const [first, second, third] = type.split(SEPARATOR);
|
|
213
|
+
INFO("parsing inputs", { first, second, third });
|
|
214
|
+
const languageInput = third ? first : void 0;
|
|
215
|
+
const actionInput = third ? second : first;
|
|
216
|
+
const formatInput = third ? third : second;
|
|
217
|
+
const language = languageSchema.parse(languageInput);
|
|
218
|
+
const action = actionsSchema.parse(actionInput);
|
|
219
|
+
const format = formatsSchema.parse(formatInput);
|
|
220
|
+
const isStart = comment.includes("start");
|
|
221
|
+
const parsed = { action, format, isStart, language, parameters };
|
|
222
|
+
INFO(`Parsed comment ${comment}`, parsed);
|
|
223
|
+
return parsed;
|
|
224
|
+
}
|
|
225
|
+
var startComment = "<!--";
|
|
226
|
+
var endComment = "-->";
|
|
227
|
+
function trimComment(comment) {
|
|
228
|
+
return comment.replace(startComment, "").replace(/start|end/, "").replace(endComment, "").trim();
|
|
229
|
+
}
|
|
230
|
+
function getComment(comment) {
|
|
231
|
+
return isComment(comment) && parseComment(comment);
|
|
232
|
+
}
|
|
233
|
+
function isComment(comment) {
|
|
234
|
+
return comment.startsWith(startComment) && comment.endsWith(endComment);
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
// src/config.ts
|
|
238
|
+
var import_cosmiconfig = require("cosmiconfig");
|
|
239
|
+
var import_deepmerge = __toESM(require("deepmerge"), 1);
|
|
240
|
+
async function loadConfig(args2) {
|
|
241
|
+
const opts2 = {};
|
|
242
|
+
if (args2.config) opts2.searchPlaces = [args2.config];
|
|
243
|
+
const explorer = (0, import_cosmiconfig.cosmiconfig)("autoreadme", opts2);
|
|
244
|
+
const search = await explorer.search();
|
|
245
|
+
if (!search) {
|
|
246
|
+
const location = args2.config ? " at location: " + args2.config : "";
|
|
247
|
+
WARN(`no config file found`, location);
|
|
248
|
+
INFO("using default configuration");
|
|
249
|
+
} else {
|
|
250
|
+
INFO("found configuration file at: ", search.filepath);
|
|
251
|
+
INFO("loaded cosmiconfig", search.config);
|
|
252
|
+
}
|
|
253
|
+
args2 = removeFalsy(args2);
|
|
254
|
+
INFO("merging config with args", args2);
|
|
255
|
+
return configSchema.parse(
|
|
256
|
+
(0, import_deepmerge.default)(search?.config || {}, args2, {
|
|
257
|
+
arrayMerge: (_, sourceArray) => sourceArray
|
|
258
|
+
})
|
|
259
|
+
);
|
|
260
|
+
}
|
|
261
|
+
function removeFalsy(obj) {
|
|
262
|
+
return Object.fromEntries(
|
|
263
|
+
Object.entries(obj).map(([k, v]) => !v ? false : [k, v]).filter((e) => Boolean(e))
|
|
264
|
+
);
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
// src/data.ts
|
|
268
|
+
var import_get_packages = require("@manypkg/get-packages");
|
|
269
|
+
var fs2 = __toESM(require("fs"), 1);
|
|
270
|
+
var fsp2 = __toESM(require("fs/promises"), 1);
|
|
271
|
+
var path2 = __toESM(require("path"), 1);
|
|
272
|
+
var import_pkg_types = require("pkg-types");
|
|
273
|
+
var yaml = __toESM(require("yaml"), 1);
|
|
274
|
+
var import_zod2md = require("zod2md");
|
|
275
|
+
|
|
276
|
+
// src/utils.ts
|
|
277
|
+
var import_fast_glob = __toESM(require("fast-glob"), 1);
|
|
278
|
+
var cp = __toESM(require("child_process"), 1);
|
|
279
|
+
var fs = __toESM(require("fs"), 1);
|
|
280
|
+
var fsp = __toESM(require("fs/promises"), 1);
|
|
281
|
+
var path = __toESM(require("path"), 1);
|
|
282
|
+
var sh = String.raw;
|
|
283
|
+
var opts = { encoding: "utf8" };
|
|
284
|
+
var ignore = ["**/node_modules/**"];
|
|
285
|
+
var matches = [
|
|
286
|
+
/.*README\.md$/gi,
|
|
287
|
+
/.*Cargo\.toml$/gi,
|
|
288
|
+
/.*action\.ya?ml$/gi,
|
|
289
|
+
/.*package\.json$/gi,
|
|
290
|
+
/.*pnpm-workspace\.yaml$/gi
|
|
291
|
+
];
|
|
292
|
+
async function fileExists(file) {
|
|
293
|
+
return await fsp.access(file).then(() => true).catch(() => false);
|
|
294
|
+
}
|
|
295
|
+
function findAffectedMarkdowns(root, config) {
|
|
296
|
+
const affected = cp.execSync(sh`git diff --cached --name-only --diff-filter=MACT`, opts).trim().split("\n").filter(Boolean);
|
|
297
|
+
if (!affected.length) ERROR("no staged files found");
|
|
298
|
+
if (config.affectedRegexes?.length) {
|
|
299
|
+
INFO("adding the following expressions: ", config.affectedRegexes);
|
|
300
|
+
}
|
|
301
|
+
const allMatches = [
|
|
302
|
+
...matches,
|
|
303
|
+
...config.affectedRegexes?.map((r) => new RegExp(r)) || []
|
|
304
|
+
];
|
|
305
|
+
INFO("Checking affected files against regexes", affected, allMatches);
|
|
306
|
+
const eligible = affected.filter((a) => allMatches.some((m) => a.match(m)));
|
|
307
|
+
INFO("Found the following eligible affected files", eligible);
|
|
308
|
+
const md = eligible.map((e) => findNearestReadme(root, path.resolve(e)));
|
|
309
|
+
const rootMd = path.join(root, "README.md");
|
|
310
|
+
const dedupe = [...new Set(md), rootMd].filter(
|
|
311
|
+
(s) => Boolean(s)
|
|
312
|
+
);
|
|
313
|
+
INFO("Found the following readmes", dedupe);
|
|
314
|
+
return dedupe;
|
|
315
|
+
}
|
|
316
|
+
function findNearestReadme(gitRoot, inputFile, maxRotations = 15) {
|
|
317
|
+
let dir = path.dirname(inputFile);
|
|
318
|
+
let rotations = 0;
|
|
319
|
+
while (true) {
|
|
320
|
+
const option = path.join(dir, "README.md");
|
|
321
|
+
if (fs.existsSync(option)) return option;
|
|
322
|
+
const parent = path.dirname(dir);
|
|
323
|
+
if (parent === dir || dir === gitRoot || ++rotations > maxRotations) {
|
|
324
|
+
break;
|
|
325
|
+
}
|
|
326
|
+
dir = parent;
|
|
327
|
+
}
|
|
328
|
+
return null;
|
|
329
|
+
}
|
|
330
|
+
function getGitRoot() {
|
|
331
|
+
const root = cp.execSync(sh`git rev-parse --show-toplevel`, opts).trim();
|
|
332
|
+
if (!root) {
|
|
333
|
+
throw new Error("must be ran within a git directory.");
|
|
334
|
+
}
|
|
335
|
+
INFO("found git root at location: ", root);
|
|
336
|
+
return root;
|
|
337
|
+
}
|
|
338
|
+
async function getMarkdownPaths(cwd, config) {
|
|
339
|
+
const pattern = `**/${config?.onlyReadmes ? "README" : "*"}.md`;
|
|
340
|
+
const readmes = await (0, import_fast_glob.default)(pattern, { cwd, ignore });
|
|
341
|
+
return readmes.map((readme) => path.resolve(cwd, readme));
|
|
342
|
+
}
|
|
343
|
+
|
|
344
|
+
// src/data.ts
|
|
345
|
+
function createFindParameter(parameterList) {
|
|
346
|
+
return function(parameterName) {
|
|
347
|
+
return parameterList?.find((p) => p.startsWith(parameterName))?.replace(parameterName + "=", "")?.replace(/"/gi, "")?.replace(/_/gi, " ");
|
|
348
|
+
};
|
|
349
|
+
}
|
|
350
|
+
async function loadActionData(actions, file, root) {
|
|
351
|
+
const startActions = actions.filter((action) => action.isStart);
|
|
352
|
+
return await Promise.all(
|
|
353
|
+
startActions.map(async (action) => {
|
|
354
|
+
const find = createFindParameter(action.parameters);
|
|
355
|
+
switch (action.action) {
|
|
356
|
+
case "ACTION": {
|
|
357
|
+
const baseDir = path2.dirname(file);
|
|
358
|
+
const actionYaml = await loadActionYaml(baseDir);
|
|
359
|
+
return {
|
|
360
|
+
action: action.action,
|
|
361
|
+
actionYaml,
|
|
362
|
+
parameters: action.parameters
|
|
363
|
+
};
|
|
364
|
+
}
|
|
365
|
+
case "PKG": {
|
|
366
|
+
const inputPath = find("path");
|
|
367
|
+
const filename = inputPath ? path2.resolve(path2.dirname(file), inputPath) : path2.dirname(file);
|
|
368
|
+
const pkgJson = await (0, import_pkg_types.readPackageJSON)(filename);
|
|
369
|
+
return {
|
|
370
|
+
action: action.action,
|
|
371
|
+
parameters: action.parameters,
|
|
372
|
+
pkgJson
|
|
373
|
+
};
|
|
374
|
+
}
|
|
375
|
+
case "USAGE": {
|
|
376
|
+
return {
|
|
377
|
+
action: action.action,
|
|
378
|
+
parameters: action.parameters
|
|
379
|
+
};
|
|
380
|
+
}
|
|
381
|
+
case "WORKSPACE": {
|
|
382
|
+
const workspaces = await (0, import_get_packages.getPackages)(process.cwd());
|
|
383
|
+
const pnpmPath = path2.resolve(root, "pnpm-workspace.yaml");
|
|
384
|
+
const isPnpm = fs2.existsSync(pnpmPath);
|
|
385
|
+
return {
|
|
386
|
+
action: action.action,
|
|
387
|
+
isPnpm,
|
|
388
|
+
parameters: action.parameters,
|
|
389
|
+
root,
|
|
390
|
+
workspaces
|
|
391
|
+
};
|
|
392
|
+
}
|
|
393
|
+
case "ZOD": {
|
|
394
|
+
if (action.format === "LIST") {
|
|
395
|
+
throw new Error("cannot display zod in list format");
|
|
396
|
+
}
|
|
397
|
+
const inputPath = find("path");
|
|
398
|
+
if (!inputPath) {
|
|
399
|
+
const error = `no path found for zod table at markdown file ${file}`;
|
|
400
|
+
throw new Error(error);
|
|
401
|
+
}
|
|
402
|
+
const body = await (0, import_zod2md.zod2md)({
|
|
403
|
+
entry: path2.resolve(path2.dirname(file), inputPath),
|
|
404
|
+
title: find("title") || "Zod Schema"
|
|
405
|
+
});
|
|
406
|
+
return {
|
|
407
|
+
action: action.action,
|
|
408
|
+
body,
|
|
409
|
+
parameters: action.parameters
|
|
410
|
+
};
|
|
411
|
+
}
|
|
412
|
+
default:
|
|
413
|
+
throw new Error("feature not yet implemented");
|
|
414
|
+
}
|
|
415
|
+
})
|
|
416
|
+
);
|
|
417
|
+
}
|
|
418
|
+
async function loadActionYaml(baseDir) {
|
|
419
|
+
const actionYmlPath = path2.resolve(baseDir, "action.yml");
|
|
420
|
+
const actionYamlPath = path2.resolve(baseDir, "action.yaml");
|
|
421
|
+
const actualPath = await fileExists(actionYamlPath) && actionYamlPath || await fileExists(actionYmlPath) && actionYmlPath;
|
|
422
|
+
if (!actualPath) {
|
|
423
|
+
const locations = [actionYmlPath, actionYamlPath];
|
|
424
|
+
const error = `no yaml file found at locations: ${locations}`;
|
|
425
|
+
throw new Error(error);
|
|
426
|
+
}
|
|
427
|
+
const actionFile = await fsp2.readFile(actualPath, { encoding: "utf8" });
|
|
428
|
+
return yaml.parse(actionFile);
|
|
429
|
+
}
|
|
430
|
+
|
|
431
|
+
// src/pipeline.ts
|
|
432
|
+
var path4 = __toESM(require("path"), 1);
|
|
433
|
+
var import_remark = require("remark");
|
|
434
|
+
var import_remark_collapse = __toESM(require("remark-collapse"), 1);
|
|
435
|
+
var import_remark_toc = __toESM(require("remark-toc"), 1);
|
|
436
|
+
var import_remark_usage = __toESM(require("remark-usage"), 1);
|
|
437
|
+
|
|
438
|
+
// src/plugin.ts
|
|
439
|
+
var import_handlebars = __toESM(require("handlebars"), 1);
|
|
440
|
+
var import_markdown_table = require("markdown-table");
|
|
441
|
+
var import_mdast_util_from_markdown = require("mdast-util-from-markdown");
|
|
442
|
+
var import_mdast_zone = require("mdast-zone");
|
|
443
|
+
var import_node_path = __toESM(require("path"), 1);
|
|
444
|
+
function createHeading(headings, disableEmojis = false, emojis = defaultTemplates.emojis) {
|
|
445
|
+
return headings.map(
|
|
446
|
+
(h) => `${disableEmojis ? "" : emojis[h] + " "}${h?.at(0)?.toUpperCase() + h?.slice(1)}`
|
|
447
|
+
);
|
|
448
|
+
}
|
|
449
|
+
function wrapRequired(required, input) {
|
|
450
|
+
if (!required) return input;
|
|
451
|
+
return `<b>*${input}</b>`;
|
|
452
|
+
}
|
|
453
|
+
var autoReadmeRemarkPlugin = (config, data) => (tree) => {
|
|
454
|
+
(0, import_mdast_zone.zone)(tree, /.*ZOD.*/gi, function(start, _, end) {
|
|
455
|
+
const zod = data.find((d) => d?.action === "ZOD");
|
|
456
|
+
if (!zod?.body) {
|
|
457
|
+
throw new Error("unable to load zod body");
|
|
458
|
+
}
|
|
459
|
+
const ast = (0, import_mdast_util_from_markdown.fromMarkdown)(zod.body);
|
|
460
|
+
return [start, ast, end];
|
|
461
|
+
});
|
|
462
|
+
(0, import_mdast_zone.zone)(tree, /.*ACTION.*/gi, function(start, _, end) {
|
|
463
|
+
const value = start.type === "html" && start.value;
|
|
464
|
+
const options = value && parseComment(value);
|
|
465
|
+
if (!options) throw new Error("not able to parse comment");
|
|
466
|
+
const first = data.find((d) => d?.action === "ACTION");
|
|
467
|
+
const inputs = first?.actionYaml?.inputs || {};
|
|
468
|
+
const heading = `### ${config.disableEmojis ? "" : "\u{1F9F0}"} actions`;
|
|
469
|
+
if (options.format === "LIST") {
|
|
470
|
+
const body2 = `${heading}
|
|
471
|
+
` + Object.entries(inputs).sort((a) => a[1].required ? -1 : 1).map(([key, value2]) => {
|
|
472
|
+
return `- ${wrapRequired(value2.required, key)}: (default: ${value2.default})
|
|
473
|
+
|
|
474
|
+
${value2.description}`;
|
|
475
|
+
}).join("\n");
|
|
476
|
+
const ast2 = (0, import_mdast_util_from_markdown.fromMarkdown)(body2);
|
|
477
|
+
return [start, ast2, end];
|
|
478
|
+
}
|
|
479
|
+
const headings = config.headings?.ACTION?.length && config.headings.ACTION || defaultTableHeadings.ACTION;
|
|
480
|
+
const table = (0, import_markdown_table.markdownTable)([
|
|
481
|
+
createHeading(
|
|
482
|
+
headings,
|
|
483
|
+
config.disableEmojis,
|
|
484
|
+
config.templates?.emojis
|
|
485
|
+
),
|
|
486
|
+
...Object.entries(inputs).map(
|
|
487
|
+
([k, v]) => headings.map((heading2) => v[heading2] || k).map(String)
|
|
488
|
+
)
|
|
489
|
+
]);
|
|
490
|
+
const body = [heading, "", table].join("\n");
|
|
491
|
+
const ast = (0, import_mdast_util_from_markdown.fromMarkdown)(body);
|
|
492
|
+
return [start, ast, end];
|
|
493
|
+
});
|
|
494
|
+
(0, import_mdast_zone.zone)(tree, /.*WORKSPACE.*/gi, function(start, _, end) {
|
|
495
|
+
const value = start.type === "html" && start.value;
|
|
496
|
+
const comment = value && parseComment(value);
|
|
497
|
+
const workspace = data.find((d) => d?.action === "WORKSPACE");
|
|
498
|
+
const templates = loadTemplates(config.templates);
|
|
499
|
+
const packages = workspace?.workspaces?.packages || [];
|
|
500
|
+
const headings = config.headings?.WORKSPACE?.length && config.headings?.WORKSPACE || defaultTableHeadings.WORKSPACE;
|
|
501
|
+
if (comment && comment.format === "LIST") {
|
|
502
|
+
}
|
|
503
|
+
const tableHeadings = createHeading(
|
|
504
|
+
headings,
|
|
505
|
+
config.disableEmojis,
|
|
506
|
+
config.templates?.emojis
|
|
507
|
+
);
|
|
508
|
+
const table = (0, import_markdown_table.markdownTable)([
|
|
509
|
+
tableHeadings,
|
|
510
|
+
...packages.filter(
|
|
511
|
+
(pkg) => config.onlyShowPublicPackages ? !pkg.packageJson.private : true
|
|
512
|
+
).map((pkg) => {
|
|
513
|
+
const { name } = pkg.packageJson;
|
|
514
|
+
return headings.map((heading2) => {
|
|
515
|
+
if (heading2 === "name") {
|
|
516
|
+
const scoped = config.removeScope ? name.replace(config.removeScope, "") : name;
|
|
517
|
+
return `[${scoped}](${import_node_path.default.relative(
|
|
518
|
+
process.cwd(),
|
|
519
|
+
import_node_path.default.resolve(pkg.dir, "README.md")
|
|
520
|
+
)})`;
|
|
521
|
+
}
|
|
522
|
+
if (heading2 === "version") {
|
|
523
|
+
return ` }
|
|
525
|
+
)})`;
|
|
526
|
+
}
|
|
527
|
+
if (heading2 === "downloads") {
|
|
528
|
+
return `})`;
|
|
531
|
+
}
|
|
532
|
+
if (heading2 === "description") {
|
|
533
|
+
return pkg.packageJson?.description;
|
|
534
|
+
}
|
|
535
|
+
return ``;
|
|
536
|
+
});
|
|
537
|
+
})
|
|
538
|
+
]);
|
|
539
|
+
const heading = `### ${config.disableEmojis ? "" : "\u{1F3ED}"} workspace`;
|
|
540
|
+
const body = [heading, "", table].join("\n");
|
|
541
|
+
const ast = (0, import_mdast_util_from_markdown.fromMarkdown)(body);
|
|
542
|
+
return [start, ast, end];
|
|
543
|
+
});
|
|
544
|
+
(0, import_mdast_zone.zone)(tree, /.*PKG.*/gi, function(start, _, end) {
|
|
545
|
+
const value = start.type === "html" && start.value;
|
|
546
|
+
const comment = value && parseComment(value);
|
|
547
|
+
const first = data.find((d) => d?.action === "PKG");
|
|
548
|
+
const templates = loadTemplates(config.templates);
|
|
549
|
+
const headings = config.headings?.PKG?.length && config.headings?.PKG || defaultTableHeadings.PKG;
|
|
550
|
+
if (comment && comment.format === "LIST") {
|
|
551
|
+
const ast = (0, import_mdast_util_from_markdown.fromMarkdown)("");
|
|
552
|
+
return [start, ast, end];
|
|
553
|
+
}
|
|
554
|
+
function mapDependencies(isDev) {
|
|
555
|
+
return function([name, version]) {
|
|
556
|
+
const url = templates.registryUrl({ name });
|
|
557
|
+
return headings.map((key) => {
|
|
558
|
+
if (key === "devDependency") {
|
|
559
|
+
if (config.disableEmojis) {
|
|
560
|
+
return `\`${isDev}\``;
|
|
561
|
+
}
|
|
562
|
+
return `${isDev ? "\u2328\uFE0F" : "\u{1F465}"}`;
|
|
563
|
+
}
|
|
564
|
+
if (key === "name") {
|
|
565
|
+
return `[${name}](${url})`;
|
|
566
|
+
}
|
|
567
|
+
if (key === "version") {
|
|
568
|
+
if (["workspace", "catalog", "*"].some(
|
|
569
|
+
(type) => version.includes(type)
|
|
570
|
+
)) {
|
|
571
|
+
return `\`${version}\``;
|
|
572
|
+
}
|
|
573
|
+
return ` })})`;
|
|
574
|
+
}
|
|
575
|
+
});
|
|
576
|
+
};
|
|
577
|
+
}
|
|
578
|
+
const { dependencies = {}, devDependencies = {} } = first?.pkgJson || {};
|
|
579
|
+
const table = (0, import_markdown_table.markdownTable)([
|
|
580
|
+
createHeading(
|
|
581
|
+
headings,
|
|
582
|
+
config.disableEmojis,
|
|
583
|
+
config.templates?.emojis
|
|
584
|
+
),
|
|
585
|
+
...Object.entries(devDependencies).map(mapDependencies(true)),
|
|
586
|
+
...Object.entries(dependencies).map(mapDependencies(false))
|
|
587
|
+
]);
|
|
588
|
+
const heading = `### ${config.disableEmojis ? "" : "\u{1F4E6}"} packages`;
|
|
589
|
+
const body = [heading, "", table].join("\n");
|
|
590
|
+
const tableAst = (0, import_mdast_util_from_markdown.fromMarkdown)(body);
|
|
591
|
+
return [start, tableAst, end];
|
|
592
|
+
});
|
|
593
|
+
};
|
|
594
|
+
function loadTemplates(templates) {
|
|
595
|
+
if (!templates) throw new Error("failed to load templates");
|
|
596
|
+
return Object.fromEntries(
|
|
597
|
+
Object.entries(templates).map(([key, value]) => {
|
|
598
|
+
if (typeof value !== "string") return [];
|
|
599
|
+
return [key, import_handlebars.default.compile(value)];
|
|
600
|
+
})
|
|
601
|
+
);
|
|
602
|
+
}
|
|
603
|
+
|
|
604
|
+
// src/pipeline.ts
|
|
605
|
+
async function parse2(file, filepath, root, config, data) {
|
|
606
|
+
const pipeline = (0, import_remark.remark)().use(autoReadmeRemarkPlugin, config, data);
|
|
607
|
+
const usage = data.find((d) => d.action === "USAGE");
|
|
608
|
+
if (usage?.action === "USAGE" || config.enableUsage) {
|
|
609
|
+
const find = createFindParameter(usage?.parameters || []);
|
|
610
|
+
const examplePath = find("path");
|
|
611
|
+
const dirname4 = path4.dirname(filepath);
|
|
612
|
+
const resolvePath = examplePath && path4.resolve(dirname4, examplePath);
|
|
613
|
+
const relativeProjectPath = config.usageFile && path4.relative(root, path4.resolve(dirname4, config.usageFile));
|
|
614
|
+
const example = examplePath && resolvePath && path4.relative(root, resolvePath) || relativeProjectPath || void 0;
|
|
615
|
+
if (await fileExists(example || "")) {
|
|
616
|
+
INFO("generating usage section");
|
|
617
|
+
pipeline.use(import_remark_usage.default, {
|
|
618
|
+
example,
|
|
619
|
+
heading: config.usageHeading
|
|
620
|
+
});
|
|
621
|
+
} else {
|
|
622
|
+
WARN("not able to find example file for readme", filepath, example);
|
|
623
|
+
}
|
|
624
|
+
}
|
|
625
|
+
if (config.enableToc) {
|
|
626
|
+
INFO("generating table of contents section");
|
|
627
|
+
pipeline.use(import_remark_toc.default, { heading: config.tocHeading }).use(import_remark_collapse.default, { test: config.tocHeading });
|
|
628
|
+
}
|
|
629
|
+
const vfile = await pipeline.process(file);
|
|
630
|
+
return vfile.toString();
|
|
631
|
+
}
|
|
632
|
+
|
|
633
|
+
// src/index.ts
|
|
634
|
+
async function run() {
|
|
635
|
+
const args2 = await parseArgs();
|
|
636
|
+
const config = await loadConfig(args2) || {};
|
|
637
|
+
INFO("Loaded the following configuration:", config);
|
|
638
|
+
const root = getGitRoot();
|
|
639
|
+
const isAffected = args2.changes ? "affected" : "";
|
|
640
|
+
INFO(`Loading ${!isAffected ? "all " : "affected "}files`);
|
|
641
|
+
const paths = isAffected ? findAffectedMarkdowns(root, config) : await getMarkdownPaths(root, config);
|
|
642
|
+
INFO("Loaded the following files:", paths.join("\n"));
|
|
643
|
+
const type = args2.onlyReadmes ? "readmes" : "all markdown files";
|
|
644
|
+
if (!paths.length) {
|
|
645
|
+
return ERROR(`no ${isAffected} readmes found to update`);
|
|
646
|
+
}
|
|
647
|
+
const spinner = !args2.verbose && (0, import_ora.default)(`Updating ${type}`).start();
|
|
648
|
+
await Promise.all(
|
|
649
|
+
paths.map(async (path5) => {
|
|
650
|
+
const file = await fsp3.readFile(path5, { encoding: "utf8" });
|
|
651
|
+
const actions = (() => {
|
|
652
|
+
const ast = (0, import_mdast_util_from_markdown2.fromMarkdown)(file);
|
|
653
|
+
return loadAstComments(ast);
|
|
654
|
+
})();
|
|
655
|
+
if (!actions.length) {
|
|
656
|
+
WARN(`no action comments found in`, path5);
|
|
657
|
+
if (!config.enableUsage || !config.enableToc) {
|
|
658
|
+
return ERROR("no action or plugins found");
|
|
659
|
+
} else {
|
|
660
|
+
INFO("plugins enabled. continuing parsing", path5);
|
|
661
|
+
}
|
|
662
|
+
}
|
|
663
|
+
const data = await loadActionData(actions, path5, root);
|
|
664
|
+
INFO("Loaded comment action data", data);
|
|
665
|
+
const content = await parse2(file, path5, root, config, data);
|
|
666
|
+
await fsp3.writeFile(path5, content);
|
|
667
|
+
})
|
|
668
|
+
);
|
|
669
|
+
if (isAffected) cp2.execFileSync("git", ["add", ...paths]);
|
|
670
|
+
if (spinner) spinner.stop();
|
|
671
|
+
}
|
|
672
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
673
|
+
0 && (module.exports = {
|
|
674
|
+
run
|
|
675
|
+
});
|
|
676
|
+
//# sourceMappingURL=index.cjs.map
|