Skip to content

Commit 0177464

Browse files
richardlauBethGriggs
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. Backport-PR-URL: #32642 PR-URL: #27661 Reviewed-By: Rich Trott <[email protected]>
1 parent 2e3d511 commit 0177464

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+
constassert=require('assert');
5+
constutil=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+
constexpected=[
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+
asyncfunctiontest(){
25+
constvers=awaitversions();
26+
// Coherence checks for each returned version.
27+
for(constversionofvers){
28+
consttested=util.inspect(version);
29+
constparts=version.num.split('.');
30+
constexpectedLength=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+
constisEvenRelease=Number.parseInt(parts[expectedLength-2])%2===0;
36+
consthasLtsProperty=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+
constthisMajor=Number.parseInt(process.versions.node.split('.')[0]);
50+
constprevMajorString=`${thisMajor-1}.x`;
51+
if(!expected.includes(prevMajorString)){
52+
expected.unshift(prevMajorString);
53+
}
54+
for(constversionofexpected){
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
constcommon=require('./common.js');
2525
constfs=require('fs');
26+
constgetVersions=require('./versions.js');
2627
constunified=require('unified');
2728
constfind=require('unist-util-find');
2829
constvisit=require('unist-util-visit');
@@ -62,7 +63,7 @@ const gtocHTML = unified()
6263
consttemplatePath=path.join(docPath,'template.html');
6364
consttemplate=fs.readFileSync(templatePath,'utf8');
6465

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

6869
constid=filename.replace(/\W+/g,'-');
@@ -80,7 +81,7 @@ function toHTML({input, content, filename, nodeVersion }, cb){
8081
constdocCreated=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__',awaitaltDocs(filename,docCreated));
8485
}else{
8586
console.error(`Failed to add alternative version links to ${filename}`);
8687
HTML=HTML.replace('__ALTDOCS__','');
@@ -380,22 +381,10 @@ function getId(text, idCounters){
380381
returntext;
381382
}
382383

383-
functionaltDocs(filename,docCreated){
384+
asyncfunctionaltDocs(filename,docCreated){
384385
const[,docCreatedMajor,docCreatedMinor]=docCreated.map(Number);
385386
consthost='https://nodejs.org';
386-
constversions=[
387-
{num: '12.x'},
388-
{num: '11.x'},
389-
{num: '10.x',lts: true},
390-
{num: '9.x'},
391-
{num: '8.x',lts: true},
392-
{num: '7.x'},
393-
{num: '6.x'},
394-
{num: '5.x'},
395-
{num: '4.x'},
396-
{num: '0.12.x'},
397-
{num: '0.10.x'}
398-
];
387+
constversions=awaitgetVersions.versions();
399388

400389
constgetHref=(versionNum)=>
401390
`${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+
constgetUrl=(url)=>{
6+
returnnewPromise((resolve,reject)=>{
7+
consthttps=require('https');
8+
constrequest=https.get(url,(response)=>{
9+
if(response.statusCode!==200){
10+
reject(newError(
11+
`Failed to get ${url}, status code ${response.statusCode}`));
12+
}
13+
response.setEncoding('utf8');
14+
letbody='';
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+
asyncversions(){
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+
constgithubContentUrl='https://raw.githubusercontent.com/nodejs/node/';
31+
constchangelog=awaitgetUrl(`${githubContentUrl}/master/CHANGELOG.md`);
32+
constltsRE=/LongTermSupport/i;
33+
constversionRE=/\*\[Node\.js([0-9.]+)\][^-]+[-]\s*(.*)\n/g;
34+
_versions=[];
35+
letmatch;
36+
while((match=versionRE.exec(changelog))!=null){
37+
constentry={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)