-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathupdate-readme.js
More file actions
132 lines (118 loc) · 4.28 KB
/
update-readme.js
File metadata and controls
132 lines (118 loc) · 4.28 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
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
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
/**
* update-readme.js
*
* Fills the Version table in README.md from .env.
* ESM module (package.json sets "type":"module"): uses import and an
* import.meta.url-derived __dirname instead of CommonJS require()/__dirname.
* Driven by: VERSION, VERSION_date, VERSION_mess
*
* Run with: npm run update-readme (called by git_steps.bat step 001)
*
* Anchoring: the table lives directly under the "## Version" heading.
* We deliberately do NOT use <!-- HTML comment --> markers: a formatter/hook
* in this workspace strips HTML comments from README.md, which would delete
* the markers on every save. The "## Version" heading is a normal Markdown
* heading the formatter keeps, so it is the stable anchor instead.
*
* On each run, everything between the "## Version" heading and the next
* non-blank / non-table line is replaced with a freshly generated table.
*
* Zero dependencies — hand-rolled .env parser (no dotenv). Lookups are
* case-insensitive (see pick()) because an editor hook lowercases the token
* "MESS" (VERSION_mess); the canonical name used here is VERSION_mess but
* any casing in .env still resolves.
*/
import fs from 'node:fs';
import path from 'node:path';
import { fileURLToPath } from 'node:url';
const __dirname = path.dirname(fileURLToPath(import.meta.url));
const ENV_PATH = path.join(__dirname, '.env');
const README_PATH = path.join(__dirname, 'README.md');
const HEADING = '## Version';
/**
* Minimal .env parser. KEY=value, optional surrounding single/double quotes,
* ignores blank lines and # comments. Keys kept as-is; use pick() to read.
* @param {string} text
* @returns {Record<string,string>}
*/
function parseEnv(text) {
const out = {};
for (const raw of text.split(/\r?\n/)) {
const line = raw.trim();
if (!line || line.startsWith('#')) continue;
const eq = line.indexOf('=');
if (eq === -1) continue;
const key = line.slice(0, eq).trim();
let val = line.slice(eq + 1).trim();
if (
(val.startsWith("'") && val.endsWith("'")) ||
(val.startsWith('"') && val.endsWith('"'))
) {
val = val.slice(1, -1);
}
out[key] = val;
}
return out;
}
/** Case-insensitive env lookup (the editor hook flips MESS<->mess casing). */
function pick(env, name) {
const want = name.toLowerCase();
for (const k of Object.keys(env)) {
if (k.toLowerCase() === want) return env[k];
}
return '';
}
/** Escape a pipe so a value can't break the markdown table. */
function cell(v) {
return String(v).replace(/\|/g, '\\|');
}
function main() {
if (!fs.existsSync(ENV_PATH)) {
console.error(`[update-readme] .env not found at ${ENV_PATH}`);
process.exit(1);
}
const env = parseEnv(fs.readFileSync(ENV_PATH, 'utf8'));
const version = pick(env, 'VERSION');
const date = pick(env, 'VERSION_date');
const mess = pick(env, 'VERSION_mess');
if (!version && !date && !mess) {
console.error(
'[update-readme] .env has no VERSION / VERSION_date / VERSION_mess — nothing to write.'
);
process.exit(1);
}
let readme = fs.readFileSync(README_PATH, 'utf8');
const eol = readme.includes('\r\n') ? '\r\n' : '\n';
if (!new RegExp(`^${HEADING}\\s*$`, 'm').test(readme)) {
console.error(
`[update-readme] "${HEADING}" heading not found in README.md. ` +
`Add a "${HEADING}" heading where the table should go, then re-run.`
);
process.exit(1);
}
const table = [
HEADING,
'',
'| Field | Value |',
'| -------------- | ------------ |',
`| \`VERSION\` | \`${cell(version)}\` |`,
`| \`VERSION_date\` | \`${cell(date)}\` |`,
`| \`VERSION_mess\` | \`${cell(mess)}\` |`,
'',
].join(eol);
// Match the heading plus any following blank lines and an existing
// markdown table (contiguous lines starting with '|'). Stops at the first
// line that is neither blank nor a table row (e.g. the intro paragraph or
// the next heading) so the rest of the README is untouched.
const region = new RegExp(
`^${HEADING}[ \\t]*\\r?\\n(?:[ \\t]*\\r?\\n|\\|[^\\r\\n]*\\r?\\n)*`,
'm'
);
readme = readme.replace(region, table + eol);
fs.writeFileSync(README_PATH, readme);
console.log(
`[update-readme] README.md Version table updated from .env:\n` +
` VERSION=${version} VERSION_date=${date} VERSION_mess=${mess}`
);
}
main();