Skip to content

Commit cc69d5a

Browse files
richardlautargos
authored andcommitted
doc,tools: get altDocs versions from CHANGELOG.md
Parse `CHANGELOG.md` for versions of Node.js used by the documentation feature `View another version` so that we don't have to manually update the list when we cut a new version or transition a release to LTS. PR-URL: #27661 Reviewed-By: Rich Trott <[email protected]>
1 parent a75a59d commit cc69d5a

File tree

3 files changed

+109
-16
lines changed

3 files changed

+109
-16
lines changed
Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
'use strict';
2+
3+
require('../common');
4+
const assert = require('assert');
5+
const util = require('util');
6+
const { versions } = require('../../tools/doc/versions.js');
7+
8+
// At the time of writing these are the minimum expected versions.
9+
// New versions of Node.js do not have to be explicitly added here.
10+
const expected = [
11+
'12.x',
12+
'11.x',
13+
'10.x',
14+
'9.x',
15+
'8.x',
16+
'7.x',
17+
'6.x',
18+
'5.x',
19+
'4.x',
20+
'0.12.x',
21+
'0.10.x',
22+
];
23+
24+
async function test() {
25+
const vers = await versions();
26+
// Coherence checks for each returned version.
27+
for (const version of vers) {
28+
const tested = util.inspect(version);
29+
const parts = version.num.split('.');
30+
const expectedLength = parts[0] === '0' ? 3 : 2;
31+
assert.strictEqual(parts.length, expectedLength,
32+
`'num' from ${tested} should be '<major>.x'.`);
33+
assert.strictEqual(parts[parts.length - 1], 'x',
34+
`'num' from ${tested} doesn't end in '.x'.`);
35+
const isEvenRelease = Number.parseInt(parts[expectedLength - 2]) % 2 === 0;
36+
const hasLtsProperty = version.hasOwnProperty('lts');
37+
if (hasLtsProperty) {
38+
// Odd-numbered versions of Node.js are never LTS.
39+
assert.ok(isEvenRelease, `${tested} should not be an 'lts' release.`);
40+
assert.ok(version.lts, `'lts' from ${tested} should 'true'.`);
41+
}
42+
}
43+
44+
// Check that the minimum number of versions were returned.
45+
// Later versions are allowed, but not checked for here (they were checked
46+
// above).
47+
// Also check for the previous semver major -- From master this will be the
48+
// most recent major release.
49+
const thisMajor = Number.parseInt(process.versions.node.split('.')[0]);
50+
const prevMajorString = `${thisMajor - 1}.x`;
51+
if (!expected.includes(prevMajorString)) {
52+
expected.unshift(prevMajorString);
53+
}
54+
for (const version of expected) {
55+
assert.ok(vers.find((x) => x.num === version),
56+
`Did not find entry for '${version}' in ${util.inspect(vers)}`);
57+
}
58+
}
59+
test();

tools/doc/html.js

Lines changed: 5 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323

2424
const common = require('./common.js');
2525
const fs = require('fs');
26+
const getVersions = require('./versions.js');
2627
const unified = require('unified');
2728
const find = require('unist-util-find');
2829
const visit = require('unist-util-visit');
@@ -62,7 +63,7 @@ const gtocHTML = unified()
6263
const templatePath = path.join(docPath, 'template.html');
6364
const template = fs.readFileSync(templatePath, 'utf8');
6465

65-
function toHTML({ input, content, filename, nodeVersion }, cb) {
66+
async function toHTML({ input, content, filename, nodeVersion }, cb) {
6667
filename = path.basename(filename, '.md');
6768

6869
const id = filename.replace(/\W+/g, '-');
@@ -80,7 +81,7 @@ function toHTML({ input, content, filename, nodeVersion }, cb) {
8081
const docCreated = input.match(
8182
/<!--\s*introduced_in\s*=\s*v([0-9]+)\.([0-9]+)\.[0-9]+\s*-->/);
8283
if (docCreated) {
83-
HTML = HTML.replace('__ALTDOCS__', altDocs(filename, docCreated));
84+
HTML = HTML.replace('__ALTDOCS__', await altDocs(filename, docCreated));
8485
} else {
8586
console.error(`Failed to add alternative version links to ${filename}`);
8687
HTML = HTML.replace('__ALTDOCS__', '');
@@ -390,22 +391,10 @@ function getId(text, idCounters) {
390391
return text;
391392
}
392393

393-
function altDocs(filename, docCreated) {
394+
async function altDocs(filename, docCreated) {
394395
const [, docCreatedMajor, docCreatedMinor] = docCreated.map(Number);
395396
const host = 'https://nodejs.org';
396-
const versions = [
397-
{ num: '12.x' },
398-
{ num: '11.x' },
399-
{ num: '10.x', lts: true },
400-
{ num: '9.x' },
401-
{ num: '8.x', lts: true },
402-
{ num: '7.x' },
403-
{ num: '6.x' },
404-
{ num: '5.x' },
405-
{ num: '4.x' },
406-
{ num: '0.12.x' },
407-
{ num: '0.10.x' },
408-
];
397+
const versions = await getVersions.versions();
409398

410399
const getHref = (versionNum) =>
411400
`${host}/docs/latest-v${versionNum}/api/${filename}.html`;

tools/doc/versions.js

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
'use strict';
2+
3+
let _versions;
4+
5+
const getUrl = (url) => {
6+
return new Promise((resolve, reject) => {
7+
const https = require('https');
8+
const request = https.get(url, (response) => {
9+
if (response.statusCode !== 200) {
10+
reject(new Error(
11+
`Failed to get ${url}, status code ${response.statusCode}`));
12+
}
13+
response.setEncoding('utf8');
14+
let body = '';
15+
response.on('data', (data) => body += data);
16+
response.on('end', () => resolve(body));
17+
});
18+
request.on('error', (err) => reject(err));
19+
});
20+
};
21+
22+
module.exports = {
23+
async versions() {
24+
if (_versions) {
25+
return _versions;
26+
}
27+
28+
// The CHANGELOG.md on release branches may not reference newer semver
29+
// majors of Node.js so fetch and parse the version from the master branch.
30+
const githubContentUrl = 'https://github.com/raw/nodejs/node/';
31+
const changelog = await getUrl(`${githubContentUrl}/master/CHANGELOG.md`);
32+
const ltsRE = /Long Term Support/i;
33+
const versionRE = /\* \[Node\.js ([0-9.]+)\][^-]+[-]\s*(.*)\n/g;
34+
_versions = [];
35+
let match;
36+
while ((match = versionRE.exec(changelog)) != null) {
37+
const entry = { num: `${match[1]}.x` };
38+
if (ltsRE.test(match[2])) {
39+
entry.lts = true;
40+
}
41+
_versions.push(entry);
42+
}
43+
return _versions;
44+
}
45+
};

0 commit comments

Comments
 (0)