github-action-readme-generator 1.12.9 → 2.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +10 -0
- package/README.md +14 -10
- package/action.yml +3 -1
- package/dist/bin/index.js +91 -10
- package/dist/mjs/index.js +90 -10
- package/package.json +3 -2
package/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,13 @@
|
|
|
1
|
+
## [2.0.0](https://github.com/bitflight-devops/github-action-readme-generator/compare/v1.12.9...v2.0.0) (2026-09-25)
|
|
2
|
+
|
|
3
|
+
### ⚠ BREAKING CHANGES
|
|
4
|
+
|
|
5
|
+
* **prettier:** format only the spans between section markers (#690)
|
|
6
|
+
|
|
7
|
+
### Bug Fixes
|
|
8
|
+
|
|
9
|
+
* **prettier:** format only the spans between section markers ([#690](https://github.com/bitflight-devops/github-action-readme-generator/issues/690)) ([f48b40d](https://github.com/bitflight-devops/github-action-readme-generator/commit/f48b40d7f03ec632f4c10957c7a2130f2d20cc7f))
|
|
10
|
+
|
|
1
11
|
## [1.12.9](https://github.com/bitflight-devops/github-action-readme-generator/compare/v1.12.8...v1.12.9) (2026-09-22)
|
|
2
12
|
|
|
3
13
|
|
package/README.md
CHANGED
|
@@ -70,11 +70,12 @@ sections whose markers you added are touched.
|
|
|
70
70
|
**Text outside the markers is yours and stays yours.** The tool replaces only
|
|
71
71
|
the span between a `start`/`end` pair.
|
|
72
72
|
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
73
|
+
**`pretty` formats the generated sections and nothing else.** With it on (the
|
|
74
|
+
default) prettier runs over each replaced span on its own — it pads the tables
|
|
75
|
+
it generated and tidies the usage block, and it never reaches your prose. A
|
|
76
|
+
first run on a file that was not already prettier-formatted changes the marker
|
|
77
|
+
sections and no other line. Run with `--pretty=false` to have the generated
|
|
78
|
+
sections written exactly as the tool composed them.
|
|
78
79
|
|
|
79
80
|
**Only yaml and markdown code blocks are reformatted; every other fence is left
|
|
80
81
|
as you wrote it.** Formatting needs a prettier plugin per language, and this tool
|
|
@@ -105,7 +106,7 @@ apply to the CLI and the Action alike.
|
|
|
105
106
|
| --paths:readme, --readme | Path to the README file | `README.md` |
|
|
106
107
|
| --owner | The GitHub Action repository owner | autodetected |
|
|
107
108
|
| --repo | The GitHub Action repository name | autodetected |
|
|
108
|
-
| --prettier, --pretty | Format the
|
|
109
|
+
| --prettier, --pretty | Format the generated sections using the prettier formatter | `true` |
|
|
109
110
|
| --versioning:enabled, --versioning | Enable the update of the usage version to match the latest version | `true` |
|
|
110
111
|
| --versioning:source, --version_source | How to detect the version: `git-tag`, `git-branch`, `git-sha`, `package-json`, `explicit` | `git-tag` |
|
|
111
112
|
| --versioning:override, --version_override, --setversion | Set a specific version to display in the README.md | unset |
|
|
@@ -118,7 +119,8 @@ apply to the CLI and the Action alike.
|
|
|
118
119
|
| --save | Save this config to `.ghadocs.json` | `false` |
|
|
119
120
|
| --debug_config, --debug_nconf | Print out the resolved config with all values, then continue | off |
|
|
120
121
|
|
|
121
|
-
To
|
|
122
|
+
To write the generated sections exactly as the tool composed them, pass the flag
|
|
123
|
+
explicitly:
|
|
122
124
|
|
|
123
125
|
```sh
|
|
124
126
|
npx github-action-readme-generator --pretty=false
|
|
@@ -267,7 +269,7 @@ value replaced by `***REDACTED***`. Keys whose names look sensitive (`auth`,
|
|
|
267
269
|
<!-- start usage -->
|
|
268
270
|
|
|
269
271
|
```yaml
|
|
270
|
-
- uses: bitflight-devops/github-action-readme-generator@v1.12.
|
|
272
|
+
- uses: bitflight-devops/github-action-readme-generator@v1.12.9
|
|
271
273
|
with:
|
|
272
274
|
# Description: The absolute or relative path to the `action.yml` file to read in
|
|
273
275
|
# from.
|
|
@@ -297,7 +299,9 @@ value replaced by `***REDACTED***`. Keys whose names look sensitive (`auth`,
|
|
|
297
299
|
# Default: false
|
|
298
300
|
save: ""
|
|
299
301
|
|
|
300
|
-
# Description: Use `prettier` to pretty print the
|
|
302
|
+
# Description: Use `prettier` to pretty print the sections this tool generates.
|
|
303
|
+
# Only the content between a section's start and end markers is formatted. The
|
|
304
|
+
# rest of the README.md file is left byte for byte as it was.
|
|
301
305
|
#
|
|
302
306
|
# Default: true
|
|
303
307
|
pretty: ""
|
|
@@ -389,7 +393,7 @@ value replaced by `***REDACTED***`. Keys whose names look sensitive (`auth`,
|
|
|
389
393
|
| <b><code>owner</code></b> | The GitHub Action repository owner, this field is autodetected by default.<br />Example: <code>bitflight-devops</code> or <code>your-gh-username</code> | | **false** |
|
|
390
394
|
| <b><code>repo</code></b> | The GitHub Action repository name, this field is autodetected by default.<br />Example: <code>github-action-readme-generator</code> | | **false** |
|
|
391
395
|
| <b><code>save</code></b> | Save the provided values in a <code>.ghadocs.json</code> file.<br />This will update any existing <code>.ghadocs.json</code> file that is in place. | <code>false</code> | **false** |
|
|
392
|
-
| <b><code>pretty</code></b> | Use <code>prettier</code> to pretty print the
|
|
396
|
+
| <b><code>pretty</code></b> | Use <code>prettier</code> to pretty print the sections this tool generates.<br />Only the content between a section's start and end markers is formatted.<br />The rest of the README.md file is left byte for byte as it was. | <code>true</code> | **false** |
|
|
393
397
|
| <b><code>versioning_enabled</code></b> | Enable the update of the usage version in the <code>uses:</code> example.<br />The version comes from whichever <code>version_source</code> selects. The default, <code>git-tag</code>, uses the latest git tag, and falls back to <code>package.json</code>, then to <code>$npm_package_version</code>, then to <code>0.0.0</code> when no tag is found — a shallow or tagless checkout takes that path.<br />Output if your action repo is <code>reviewdog/action-eslint</code> and the latest tag is <code>v1.0.1</code>:<br /><code>uses: reviewdog/action-eslint@v1.0.1</code> | <code>true</code> | **false** |
|
|
394
398
|
| <b><code>version_override</code></b> | Set a specific version to display in the README.md, maybe you want to use a major or minor version | | **false** |
|
|
395
399
|
| <b><code>version_prefix</code></b> | Prefix the version with this value, if it isn't already prefixed | <code>v</code> | **false** |
|
package/action.yml
CHANGED
|
@@ -36,7 +36,9 @@ inputs:
|
|
|
36
36
|
default: false
|
|
37
37
|
pretty:
|
|
38
38
|
description: |
|
|
39
|
-
Use `prettier` to pretty print the
|
|
39
|
+
Use `prettier` to pretty print the sections this tool generates.
|
|
40
|
+
Only the content between a section's start and end markers is formatted.
|
|
41
|
+
The rest of the README.md file is left byte for byte as it was.
|
|
40
42
|
required: false
|
|
41
43
|
default: 'true'
|
|
42
44
|
versioning_enabled:
|
package/dist/bin/index.js
CHANGED
|
@@ -18,7 +18,7 @@ import { fileURLToPath } from "node:url";
|
|
|
18
18
|
import * as child from "child_process";
|
|
19
19
|
import { setTimeout as setTimeout$1 } from "timers";
|
|
20
20
|
import process$1 from "node:process";
|
|
21
|
-
import os$1
|
|
21
|
+
import os$1 from "node:os";
|
|
22
22
|
import tty from "node:tty";
|
|
23
23
|
import { execFileSync, execSync } from "node:child_process";
|
|
24
24
|
//#region \0rolldown/runtime.js
|
|
@@ -67023,14 +67023,51 @@ const startTokenFormat = "(^|[^`\\\\])<!--\\s+start\\s+%s\\s+-->";
|
|
|
67023
67023
|
* The format for the end token of a section.
|
|
67024
67024
|
*/
|
|
67025
67025
|
const endTokenFormat = "(^|[^`\\\\])<!--\\s+end\\s+%s\\s+-->";
|
|
67026
|
+
/**
|
|
67027
|
+
* Lays out section content the way it sits between its markers.
|
|
67028
|
+
* @param {string} content - The trimmed section content.
|
|
67029
|
+
* @param {boolean} addNewlines - Whether to pad the content with newlines.
|
|
67030
|
+
* @returns {string} - The text that goes between the markers.
|
|
67031
|
+
*/
|
|
67032
|
+
function layoutSpan(content, addNewlines) {
|
|
67033
|
+
return addNewlines ? `\n\n${content}\n` : content;
|
|
67034
|
+
}
|
|
67035
|
+
/**
|
|
67036
|
+
* True when every line break in `text` is CRLF, and there is at least one.
|
|
67037
|
+
*
|
|
67038
|
+
* Only a document that is CRLF throughout is edited as CRLF. Removing the `\r`
|
|
67039
|
+
* before each `\n` and adding it back is then an exact round trip, so the
|
|
67040
|
+
* bytes outside the markers survive. A document that mixes the two is left as
|
|
67041
|
+
* it is, since no single ending would reproduce it.
|
|
67042
|
+
* @param {string} text - The document.
|
|
67043
|
+
* @returns {boolean} - Whether the document uses CRLF line endings.
|
|
67044
|
+
*/
|
|
67045
|
+
function usesCrlf(text) {
|
|
67046
|
+
return text.includes("\r\n") && !/(^|[^\r])\n/.test(text);
|
|
67047
|
+
}
|
|
67026
67048
|
var ReadmeEditor = class {
|
|
67027
67049
|
log = new LogTask("ReadmeEditor");
|
|
67028
67050
|
/**
|
|
67029
67051
|
* The path to the README file.
|
|
67030
67052
|
*/
|
|
67031
67053
|
filePath;
|
|
67054
|
+
/**
|
|
67055
|
+
* The document with LF line endings, whatever the file uses. Every edit and
|
|
67056
|
+
* every formatter pass works on LF; `dumpToFile` restores the file's own
|
|
67057
|
+
* ending on the way out.
|
|
67058
|
+
*/
|
|
67032
67059
|
fileContent;
|
|
67033
67060
|
/**
|
|
67061
|
+
* Whether the file on disk is CRLF throughout — see `usesCrlf`.
|
|
67062
|
+
*/
|
|
67063
|
+
crlf = false;
|
|
67064
|
+
/**
|
|
67065
|
+
* The padded sections this editor has replaced, each against the content it
|
|
67066
|
+
* wrote. `dumpToFile` formats these spans and nothing else — see
|
|
67067
|
+
* `formatUpdatedSections`.
|
|
67068
|
+
*/
|
|
67069
|
+
updatedSections = /* @__PURE__ */ new Map();
|
|
67070
|
+
/**
|
|
67034
67071
|
* Creates a new instance of `ReadmeEditor`.
|
|
67035
67072
|
* @param {string} filePath - The path to the README file.
|
|
67036
67073
|
*/
|
|
@@ -67038,15 +67075,17 @@ var ReadmeEditor = class {
|
|
|
67038
67075
|
this.filePath = filePath;
|
|
67039
67076
|
try {
|
|
67040
67077
|
fs$3.accessSync(filePath);
|
|
67041
|
-
|
|
67042
|
-
if (process.env.GITHUB_ACTIONS) setOutput("readme_before",
|
|
67078
|
+
const raw = fs$3.readFileSync(filePath, "utf8");
|
|
67079
|
+
if (process.env.GITHUB_ACTIONS) setOutput("readme_before", raw);
|
|
67080
|
+
this.crlf = usesCrlf(raw);
|
|
67081
|
+
this.fileContent = this.crlf ? raw.replaceAll("\r\n", "\n") : raw;
|
|
67043
67082
|
} catch (error) {
|
|
67044
67083
|
this.log.fail(`Readme at '${filePath}' does not exist.`);
|
|
67045
67084
|
throw error;
|
|
67046
67085
|
}
|
|
67047
67086
|
}
|
|
67048
67087
|
/**
|
|
67049
|
-
* Gets the current README content.
|
|
67088
|
+
* Gets the current README content, with LF line endings.
|
|
67050
67089
|
* @returns {string} - The README file content.
|
|
67051
67090
|
*/
|
|
67052
67091
|
getReadmeContent() {
|
|
@@ -67081,24 +67120,66 @@ var ReadmeEditor = class {
|
|
|
67081
67120
|
*/
|
|
67082
67121
|
updateSection(name, providedContent, addNewlines = true) {
|
|
67083
67122
|
const log = new LogTask(name);
|
|
67084
|
-
const content = (Array.isArray(providedContent) ? providedContent.join(
|
|
67123
|
+
const content = (Array.isArray(providedContent) ? providedContent.join("\n") : providedContent ?? "").replaceAll("\r\n", "\n").trim();
|
|
67085
67124
|
log.info(`Looking for the ${name} token in ${this.filePath}`);
|
|
67086
67125
|
const [startIndex, stopIndex] = this.getTokenIndexes(name, log);
|
|
67087
67126
|
if (startIndex && stopIndex) {
|
|
67088
67127
|
const beforeContent = this.fileContent.slice(0, startIndex);
|
|
67089
67128
|
const afterContent = this.fileContent.slice(stopIndex);
|
|
67090
|
-
this.fileContent =
|
|
67129
|
+
this.fileContent = `${beforeContent}${layoutSpan(content, addNewlines)}${afterContent}`;
|
|
67130
|
+
if (addNewlines) this.updatedSections.set(name, content);
|
|
67091
67131
|
}
|
|
67092
67132
|
}
|
|
67093
67133
|
/**
|
|
67134
|
+
* Formats the span of one section in isolation and splices it back.
|
|
67135
|
+
*
|
|
67136
|
+
* The content is formatted on its own and reassembled with the same
|
|
67137
|
+
* surrounding newlines `updateSection` wrote, so the markers and every byte
|
|
67138
|
+
* outside them survive untouched.
|
|
67139
|
+
*
|
|
67140
|
+
* The span is formatted only while its markers still bound exactly the text
|
|
67141
|
+
* `updateSection` wrote. The markers are paired again here, after every
|
|
67142
|
+
* section has been written, and a marker another section wrote can win that
|
|
67143
|
+
* pairing; the text between such a pair is not this tool's to format.
|
|
67144
|
+
* @param {string} name - The name of the section.
|
|
67145
|
+
* @param {string} content - The content `updateSection` wrote, padded.
|
|
67146
|
+
*/
|
|
67147
|
+
async formatSection(name, content) {
|
|
67148
|
+
const [startIndex, stopIndex] = this.getTokenIndexes(name);
|
|
67149
|
+
if (!startIndex || !stopIndex) return;
|
|
67150
|
+
if (startIndex > stopIndex || this.fileContent.slice(startIndex, stopIndex) !== layoutSpan(content, true)) {
|
|
67151
|
+
this.log.warn(`The '${name}' markers no longer bound the text written to them. Leaving the section unformatted`);
|
|
67152
|
+
return;
|
|
67153
|
+
}
|
|
67154
|
+
const formatted = content === "" ? "" : (await formatMarkdown(content)).trim();
|
|
67155
|
+
const span = formatted === "" ? "\n" : layoutSpan(formatted, true);
|
|
67156
|
+
this.fileContent = `${this.fileContent.slice(0, startIndex)}${span}${this.fileContent.slice(stopIndex)}`;
|
|
67157
|
+
}
|
|
67158
|
+
/**
|
|
67159
|
+
* Formats every span this editor replaced, one span at a time.
|
|
67160
|
+
*
|
|
67161
|
+
* Each span is located again before it is formatted, because formatting the
|
|
67162
|
+
* previous one moves the indexes of the spans after it. A formatted span no
|
|
67163
|
+
* longer holds the text `updateSection` wrote, so it is forgotten once
|
|
67164
|
+
* formatted.
|
|
67165
|
+
* @returns {Promise<void>}
|
|
67166
|
+
*/
|
|
67167
|
+
async formatUpdatedSections() {
|
|
67168
|
+
for (const [name, content] of this.updatedSections) await this.formatSection(name, content);
|
|
67169
|
+
this.updatedSections.clear();
|
|
67170
|
+
}
|
|
67171
|
+
/**
|
|
67094
67172
|
* Dumps the modified content back to the README file.
|
|
67095
|
-
* @param {boolean} [prettier=true] - Run the
|
|
67096
|
-
* writing. Callers pass the resolved `pretty` input; it defaults to
|
|
67097
|
-
* constructing a ReadmeEditor directly keeps the formatting
|
|
67173
|
+
* @param {boolean} [prettier=true] - Run the replaced spans through prettier
|
|
67174
|
+
* before writing. Callers pass the resolved `pretty` input; it defaults to
|
|
67175
|
+
* true so constructing a ReadmeEditor directly keeps the formatting
|
|
67176
|
+
* behaviour. Text outside the markers is never formatted, whatever this
|
|
67177
|
+
* flag says — see `docs/tool-contract.md`.
|
|
67098
67178
|
* @returns {Promise<void>}
|
|
67099
67179
|
*/
|
|
67100
67180
|
async dumpToFile(prettier = true) {
|
|
67101
|
-
|
|
67181
|
+
if (prettier) await this.formatUpdatedSections();
|
|
67182
|
+
const content = this.crlf ? this.fileContent.replaceAll("\n", "\r\n") : this.fileContent;
|
|
67102
67183
|
if (process.env.GITHUB_ACTIONS) setOutput("readme_after", content);
|
|
67103
67184
|
return fs$3.promises.writeFile(this.filePath, content, "utf8");
|
|
67104
67185
|
}
|
package/dist/mjs/index.js
CHANGED
|
@@ -10,7 +10,6 @@ import * as feather from "feather-icons";
|
|
|
10
10
|
import { icons } from "feather-icons";
|
|
11
11
|
import chalkPkg from "chalk";
|
|
12
12
|
import { execFileSync, execSync } from "node:child_process";
|
|
13
|
-
import { EOL } from "node:os";
|
|
14
13
|
import * as markdown from "prettier/plugins/markdown";
|
|
15
14
|
import * as yaml from "prettier/plugins/yaml";
|
|
16
15
|
import { format } from "prettier/standalone";
|
|
@@ -860,14 +859,51 @@ const startTokenFormat = "(^|[^`\\\\])<!--\\s+start\\s+%s\\s+-->";
|
|
|
860
859
|
* The format for the end token of a section.
|
|
861
860
|
*/
|
|
862
861
|
const endTokenFormat = "(^|[^`\\\\])<!--\\s+end\\s+%s\\s+-->";
|
|
862
|
+
/**
|
|
863
|
+
* Lays out section content the way it sits between its markers.
|
|
864
|
+
* @param {string} content - The trimmed section content.
|
|
865
|
+
* @param {boolean} addNewlines - Whether to pad the content with newlines.
|
|
866
|
+
* @returns {string} - The text that goes between the markers.
|
|
867
|
+
*/
|
|
868
|
+
function layoutSpan(content, addNewlines) {
|
|
869
|
+
return addNewlines ? `\n\n${content}\n` : content;
|
|
870
|
+
}
|
|
871
|
+
/**
|
|
872
|
+
* True when every line break in `text` is CRLF, and there is at least one.
|
|
873
|
+
*
|
|
874
|
+
* Only a document that is CRLF throughout is edited as CRLF. Removing the `\r`
|
|
875
|
+
* before each `\n` and adding it back is then an exact round trip, so the
|
|
876
|
+
* bytes outside the markers survive. A document that mixes the two is left as
|
|
877
|
+
* it is, since no single ending would reproduce it.
|
|
878
|
+
* @param {string} text - The document.
|
|
879
|
+
* @returns {boolean} - Whether the document uses CRLF line endings.
|
|
880
|
+
*/
|
|
881
|
+
function usesCrlf(text) {
|
|
882
|
+
return text.includes("\r\n") && !/(^|[^\r])\n/.test(text);
|
|
883
|
+
}
|
|
863
884
|
var ReadmeEditor = class {
|
|
864
885
|
log = new LogTask("ReadmeEditor");
|
|
865
886
|
/**
|
|
866
887
|
* The path to the README file.
|
|
867
888
|
*/
|
|
868
889
|
filePath;
|
|
890
|
+
/**
|
|
891
|
+
* The document with LF line endings, whatever the file uses. Every edit and
|
|
892
|
+
* every formatter pass works on LF; `dumpToFile` restores the file's own
|
|
893
|
+
* ending on the way out.
|
|
894
|
+
*/
|
|
869
895
|
fileContent;
|
|
870
896
|
/**
|
|
897
|
+
* Whether the file on disk is CRLF throughout — see `usesCrlf`.
|
|
898
|
+
*/
|
|
899
|
+
crlf = false;
|
|
900
|
+
/**
|
|
901
|
+
* The padded sections this editor has replaced, each against the content it
|
|
902
|
+
* wrote. `dumpToFile` formats these spans and nothing else — see
|
|
903
|
+
* `formatUpdatedSections`.
|
|
904
|
+
*/
|
|
905
|
+
updatedSections = /* @__PURE__ */ new Map();
|
|
906
|
+
/**
|
|
871
907
|
* Creates a new instance of `ReadmeEditor`.
|
|
872
908
|
* @param {string} filePath - The path to the README file.
|
|
873
909
|
*/
|
|
@@ -875,15 +911,17 @@ var ReadmeEditor = class {
|
|
|
875
911
|
this.filePath = filePath;
|
|
876
912
|
try {
|
|
877
913
|
fs.accessSync(filePath);
|
|
878
|
-
|
|
879
|
-
if (process.env.GITHUB_ACTIONS) core.setOutput("readme_before",
|
|
914
|
+
const raw = fs.readFileSync(filePath, "utf8");
|
|
915
|
+
if (process.env.GITHUB_ACTIONS) core.setOutput("readme_before", raw);
|
|
916
|
+
this.crlf = usesCrlf(raw);
|
|
917
|
+
this.fileContent = this.crlf ? raw.replaceAll("\r\n", "\n") : raw;
|
|
880
918
|
} catch (error) {
|
|
881
919
|
this.log.fail(`Readme at '${filePath}' does not exist.`);
|
|
882
920
|
throw error;
|
|
883
921
|
}
|
|
884
922
|
}
|
|
885
923
|
/**
|
|
886
|
-
* Gets the current README content.
|
|
924
|
+
* Gets the current README content, with LF line endings.
|
|
887
925
|
* @returns {string} - The README file content.
|
|
888
926
|
*/
|
|
889
927
|
getReadmeContent() {
|
|
@@ -918,24 +956,66 @@ var ReadmeEditor = class {
|
|
|
918
956
|
*/
|
|
919
957
|
updateSection(name, providedContent, addNewlines = true) {
|
|
920
958
|
const log = new LogTask(name);
|
|
921
|
-
const content = (Array.isArray(providedContent) ? providedContent.join(
|
|
959
|
+
const content = (Array.isArray(providedContent) ? providedContent.join("\n") : providedContent ?? "").replaceAll("\r\n", "\n").trim();
|
|
922
960
|
log.info(`Looking for the ${name} token in ${this.filePath}`);
|
|
923
961
|
const [startIndex, stopIndex] = this.getTokenIndexes(name, log);
|
|
924
962
|
if (startIndex && stopIndex) {
|
|
925
963
|
const beforeContent = this.fileContent.slice(0, startIndex);
|
|
926
964
|
const afterContent = this.fileContent.slice(stopIndex);
|
|
927
|
-
this.fileContent =
|
|
965
|
+
this.fileContent = `${beforeContent}${layoutSpan(content, addNewlines)}${afterContent}`;
|
|
966
|
+
if (addNewlines) this.updatedSections.set(name, content);
|
|
928
967
|
}
|
|
929
968
|
}
|
|
930
969
|
/**
|
|
970
|
+
* Formats the span of one section in isolation and splices it back.
|
|
971
|
+
*
|
|
972
|
+
* The content is formatted on its own and reassembled with the same
|
|
973
|
+
* surrounding newlines `updateSection` wrote, so the markers and every byte
|
|
974
|
+
* outside them survive untouched.
|
|
975
|
+
*
|
|
976
|
+
* The span is formatted only while its markers still bound exactly the text
|
|
977
|
+
* `updateSection` wrote. The markers are paired again here, after every
|
|
978
|
+
* section has been written, and a marker another section wrote can win that
|
|
979
|
+
* pairing; the text between such a pair is not this tool's to format.
|
|
980
|
+
* @param {string} name - The name of the section.
|
|
981
|
+
* @param {string} content - The content `updateSection` wrote, padded.
|
|
982
|
+
*/
|
|
983
|
+
async formatSection(name, content) {
|
|
984
|
+
const [startIndex, stopIndex] = this.getTokenIndexes(name);
|
|
985
|
+
if (!startIndex || !stopIndex) return;
|
|
986
|
+
if (startIndex > stopIndex || this.fileContent.slice(startIndex, stopIndex) !== layoutSpan(content, true)) {
|
|
987
|
+
this.log.warn(`The '${name}' markers no longer bound the text written to them. Leaving the section unformatted`);
|
|
988
|
+
return;
|
|
989
|
+
}
|
|
990
|
+
const formatted = content === "" ? "" : (await formatMarkdown(content)).trim();
|
|
991
|
+
const span = formatted === "" ? "\n" : layoutSpan(formatted, true);
|
|
992
|
+
this.fileContent = `${this.fileContent.slice(0, startIndex)}${span}${this.fileContent.slice(stopIndex)}`;
|
|
993
|
+
}
|
|
994
|
+
/**
|
|
995
|
+
* Formats every span this editor replaced, one span at a time.
|
|
996
|
+
*
|
|
997
|
+
* Each span is located again before it is formatted, because formatting the
|
|
998
|
+
* previous one moves the indexes of the spans after it. A formatted span no
|
|
999
|
+
* longer holds the text `updateSection` wrote, so it is forgotten once
|
|
1000
|
+
* formatted.
|
|
1001
|
+
* @returns {Promise<void>}
|
|
1002
|
+
*/
|
|
1003
|
+
async formatUpdatedSections() {
|
|
1004
|
+
for (const [name, content] of this.updatedSections) await this.formatSection(name, content);
|
|
1005
|
+
this.updatedSections.clear();
|
|
1006
|
+
}
|
|
1007
|
+
/**
|
|
931
1008
|
* Dumps the modified content back to the README file.
|
|
932
|
-
* @param {boolean} [prettier=true] - Run the
|
|
933
|
-
* writing. Callers pass the resolved `pretty` input; it defaults to
|
|
934
|
-
* constructing a ReadmeEditor directly keeps the formatting
|
|
1009
|
+
* @param {boolean} [prettier=true] - Run the replaced spans through prettier
|
|
1010
|
+
* before writing. Callers pass the resolved `pretty` input; it defaults to
|
|
1011
|
+
* true so constructing a ReadmeEditor directly keeps the formatting
|
|
1012
|
+
* behaviour. Text outside the markers is never formatted, whatever this
|
|
1013
|
+
* flag says — see `docs/tool-contract.md`.
|
|
935
1014
|
* @returns {Promise<void>}
|
|
936
1015
|
*/
|
|
937
1016
|
async dumpToFile(prettier = true) {
|
|
938
|
-
|
|
1017
|
+
if (prettier) await this.formatUpdatedSections();
|
|
1018
|
+
const content = this.crlf ? this.fileContent.replaceAll("\n", "\r\n") : this.fileContent;
|
|
939
1019
|
if (process.env.GITHUB_ACTIONS) core.setOutput("readme_after", content);
|
|
940
1020
|
return fs.promises.writeFile(this.filePath, content, "utf8");
|
|
941
1021
|
}
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "github-action-readme-generator",
|
|
3
3
|
"displayName": "bitflight-devops/github-action-readme-generator",
|
|
4
|
-
"version": "
|
|
4
|
+
"version": "2.0.0",
|
|
5
5
|
"description": "The docs generator for GitHub Actions. Auto-syncs action.yml to README.md with 8 sections: inputs, outputs, usage, badges, branding & more. Works as CLI or GitHub Action.",
|
|
6
6
|
"keywords": [
|
|
7
7
|
"github-actions",
|
|
@@ -128,7 +128,7 @@
|
|
|
128
128
|
"@semantic-release/github",
|
|
129
129
|
"@semantic-release/git"
|
|
130
130
|
],
|
|
131
|
-
"preset": "
|
|
131
|
+
"preset": "conventionalcommits"
|
|
132
132
|
},
|
|
133
133
|
"dependencies": {
|
|
134
134
|
"@actions/core": "^3.0.0",
|
|
@@ -156,6 +156,7 @@
|
|
|
156
156
|
"@vitest/coverage-v8": "4.1.11",
|
|
157
157
|
"@voidzero-dev/vite-plus-core": "0.2.8",
|
|
158
158
|
"commitizen": "^4.3.1",
|
|
159
|
+
"conventional-changelog-conventionalcommits": "^9.3.1",
|
|
159
160
|
"conventional-commits": "^1.6.0",
|
|
160
161
|
"cz-conventional-changelog": "^3.3.0",
|
|
161
162
|
"dotenv": "^17.2.4",
|