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