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