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: https://github.com/nodejs/node/pull/27661 Reviewed-By: Rich Trott <rtrott@gmail.com>
This commit is contained in:
parent
5aaa7fee2e
commit
4ec6135c71
59
test/internet/test-doctool-versions.js
Normal file
59
test/internet/test-doctool-versions.js
Normal file
@ -0,0 +1,59 @@
|
|||||||
|
'use strict';
|
||||||
|
|
||||||
|
require('../common');
|
||||||
|
const assert = require('assert');
|
||||||
|
const util = require('util');
|
||||||
|
const { versions } = require('../../tools/doc/versions.js');
|
||||||
|
|
||||||
|
// At the time of writing these are the minimum expected versions.
|
||||||
|
// New versions of Node.js do not have to be explicitly added here.
|
||||||
|
const expected = [
|
||||||
|
'12.x',
|
||||||
|
'11.x',
|
||||||
|
'10.x',
|
||||||
|
'9.x',
|
||||||
|
'8.x',
|
||||||
|
'7.x',
|
||||||
|
'6.x',
|
||||||
|
'5.x',
|
||||||
|
'4.x',
|
||||||
|
'0.12.x',
|
||||||
|
'0.10.x',
|
||||||
|
];
|
||||||
|
|
||||||
|
async function test() {
|
||||||
|
const vers = await versions();
|
||||||
|
// Coherence checks for each returned version.
|
||||||
|
for (const version of vers) {
|
||||||
|
const tested = util.inspect(version);
|
||||||
|
const parts = version.num.split('.');
|
||||||
|
const expectedLength = parts[0] === '0' ? 3 : 2;
|
||||||
|
assert.strictEqual(parts.length, expectedLength,
|
||||||
|
`'num' from ${tested} should be '<major>.x'.`);
|
||||||
|
assert.strictEqual(parts[parts.length - 1], 'x',
|
||||||
|
`'num' from ${tested} doesn't end in '.x'.`);
|
||||||
|
const isEvenRelease = Number.parseInt(parts[expectedLength - 2]) % 2 === 0;
|
||||||
|
const hasLtsProperty = version.hasOwnProperty('lts');
|
||||||
|
if (hasLtsProperty) {
|
||||||
|
// Odd-numbered versions of Node.js are never LTS.
|
||||||
|
assert.ok(isEvenRelease, `${tested} should not be an 'lts' release.`);
|
||||||
|
assert.ok(version.lts, `'lts' from ${tested} should 'true'.`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check that the minimum number of versions were returned.
|
||||||
|
// Later versions are allowed, but not checked for here (they were checked
|
||||||
|
// above).
|
||||||
|
// Also check for the previous semver major -- From master this will be the
|
||||||
|
// most recent major release.
|
||||||
|
const thisMajor = Number.parseInt(process.versions.node.split('.')[0]);
|
||||||
|
const prevMajorString = `${thisMajor - 1}.x`;
|
||||||
|
if (!expected.includes(prevMajorString)) {
|
||||||
|
expected.unshift(prevMajorString);
|
||||||
|
}
|
||||||
|
for (const version of expected) {
|
||||||
|
assert.ok(vers.find((x) => x.num === version),
|
||||||
|
`Did not find entry for '${version}' in ${util.inspect(vers)}`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
test();
|
@ -23,6 +23,7 @@
|
|||||||
|
|
||||||
const common = require('./common.js');
|
const common = require('./common.js');
|
||||||
const fs = require('fs');
|
const fs = require('fs');
|
||||||
|
const getVersions = require('./versions.js');
|
||||||
const unified = require('unified');
|
const unified = require('unified');
|
||||||
const find = require('unist-util-find');
|
const find = require('unist-util-find');
|
||||||
const visit = require('unist-util-visit');
|
const visit = require('unist-util-visit');
|
||||||
@ -62,7 +63,7 @@ const gtocHTML = unified()
|
|||||||
const templatePath = path.join(docPath, 'template.html');
|
const templatePath = path.join(docPath, 'template.html');
|
||||||
const template = fs.readFileSync(templatePath, 'utf8');
|
const template = fs.readFileSync(templatePath, 'utf8');
|
||||||
|
|
||||||
function toHTML({ input, content, filename, nodeVersion }, cb) {
|
async function toHTML({ input, content, filename, nodeVersion }, cb) {
|
||||||
filename = path.basename(filename, '.md');
|
filename = path.basename(filename, '.md');
|
||||||
|
|
||||||
const id = filename.replace(/\W+/g, '-');
|
const id = filename.replace(/\W+/g, '-');
|
||||||
@ -80,7 +81,7 @@ function toHTML({ input, content, filename, nodeVersion }, cb) {
|
|||||||
const docCreated = input.match(
|
const docCreated = input.match(
|
||||||
/<!--\s*introduced_in\s*=\s*v([0-9]+)\.([0-9]+)\.[0-9]+\s*-->/);
|
/<!--\s*introduced_in\s*=\s*v([0-9]+)\.([0-9]+)\.[0-9]+\s*-->/);
|
||||||
if (docCreated) {
|
if (docCreated) {
|
||||||
HTML = HTML.replace('__ALTDOCS__', altDocs(filename, docCreated));
|
HTML = HTML.replace('__ALTDOCS__', await altDocs(filename, docCreated));
|
||||||
} else {
|
} else {
|
||||||
console.error(`Failed to add alternative version links to ${filename}`);
|
console.error(`Failed to add alternative version links to ${filename}`);
|
||||||
HTML = HTML.replace('__ALTDOCS__', '');
|
HTML = HTML.replace('__ALTDOCS__', '');
|
||||||
@ -390,22 +391,10 @@ function getId(text, idCounters) {
|
|||||||
return text;
|
return text;
|
||||||
}
|
}
|
||||||
|
|
||||||
function altDocs(filename, docCreated) {
|
async function altDocs(filename, docCreated) {
|
||||||
const [, docCreatedMajor, docCreatedMinor] = docCreated.map(Number);
|
const [, docCreatedMajor, docCreatedMinor] = docCreated.map(Number);
|
||||||
const host = 'https://nodejs.org';
|
const host = 'https://nodejs.org';
|
||||||
const versions = [
|
const versions = await getVersions.versions();
|
||||||
{ num: '12.x' },
|
|
||||||
{ num: '11.x' },
|
|
||||||
{ num: '10.x', lts: true },
|
|
||||||
{ num: '9.x' },
|
|
||||||
{ num: '8.x', lts: true },
|
|
||||||
{ num: '7.x' },
|
|
||||||
{ num: '6.x' },
|
|
||||||
{ num: '5.x' },
|
|
||||||
{ num: '4.x' },
|
|
||||||
{ num: '0.12.x' },
|
|
||||||
{ num: '0.10.x' },
|
|
||||||
];
|
|
||||||
|
|
||||||
const getHref = (versionNum) =>
|
const getHref = (versionNum) =>
|
||||||
`${host}/docs/latest-v${versionNum}/api/${filename}.html`;
|
`${host}/docs/latest-v${versionNum}/api/${filename}.html`;
|
||||||
|
45
tools/doc/versions.js
Normal file
45
tools/doc/versions.js
Normal file
@ -0,0 +1,45 @@
|
|||||||
|
'use strict';
|
||||||
|
|
||||||
|
let _versions;
|
||||||
|
|
||||||
|
const getUrl = (url) => {
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
const https = require('https');
|
||||||
|
const request = https.get(url, (response) => {
|
||||||
|
if (response.statusCode !== 200) {
|
||||||
|
reject(new Error(
|
||||||
|
`Failed to get ${url}, status code ${response.statusCode}`));
|
||||||
|
}
|
||||||
|
response.setEncoding('utf8');
|
||||||
|
let body = '';
|
||||||
|
response.on('data', (data) => body += data);
|
||||||
|
response.on('end', () => resolve(body));
|
||||||
|
});
|
||||||
|
request.on('error', (err) => reject(err));
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
async versions() {
|
||||||
|
if (_versions) {
|
||||||
|
return _versions;
|
||||||
|
}
|
||||||
|
|
||||||
|
// The CHANGELOG.md on release branches may not reference newer semver
|
||||||
|
// majors of Node.js so fetch and parse the version from the master branch.
|
||||||
|
const githubContentUrl = 'https://raw.githubusercontent.com/nodejs/node/';
|
||||||
|
const changelog = await getUrl(`${githubContentUrl}/master/CHANGELOG.md`);
|
||||||
|
const ltsRE = /Long Term Support/i;
|
||||||
|
const versionRE = /\* \[Node\.js ([0-9.]+)\][^-—]+[-—]\s*(.*)\n/g;
|
||||||
|
_versions = [];
|
||||||
|
let match;
|
||||||
|
while ((match = versionRE.exec(changelog)) != null) {
|
||||||
|
const entry = { num: `${match[1]}.x` };
|
||||||
|
if (ltsRE.test(match[2])) {
|
||||||
|
entry.lts = true;
|
||||||
|
}
|
||||||
|
_versions.push(entry);
|
||||||
|
}
|
||||||
|
return _versions;
|
||||||
|
}
|
||||||
|
};
|
Loading…
x
Reference in New Issue
Block a user