blob: 9b87bb29ef2c858e948a2365694ea202ee153437 [file] [log] [blame]
// Run this to update the ToCs in the TRs
const { generateGfmToc } = require('@not-dalia/gfm-toc');
const fs = require('fs').promises;
const path = require('path');
const dir = '../../../docs/ldml';
const trfile = /^tr35.*\.md$/;
const contentsStart = /^## <a name="Contents".*$/; // beginning of contents: always has #Contents
const contentsEnd = /^## .*$/; // end of contents: the next ##
// ToC entries we don't want, for deletion
const tocDelete = [
/^[ ]*\* \[.*Unicode Technical Standard.*$/,
/^[ ]*\* \[_Summary_\].*$/,
/^[ ]*\* \[_Status_\].*$/,
/^[ ]*\* \[Parts\].*$/,
/^[ ]*\* \[Contents of.*$/
];
const gfmOpts = {
// see gfm-toc docs
includeUnlinked: true,
createLinks: true,
};
/**
*
* @returns promise to array of source files
*/
async function getSrcFiles() {
const f = [];
const items = await fs.opendir(dir);
for await (const dirent of items) {
if (trfile.test(dirent.name)) {
f.push(path.join(dir, dirent.name));
}
}
return f;
}
/**
* Process a single file
* @param {String} f
* @returns
*/
async function processFile(f) {
console.log('Reading: ' + f);
const contents = await fs.readFile(f, 'utf-8');
// now, reinsert
const lines = contents.split(/(?:\r)?\n/);
// new lines go into this array.
const out = [];
let i;
// go through the lines, looking for the header to the old ToC.
for (i = 0; i < lines.length; i++) {
out.push(lines[i]); // Emit the header line for the old ToC
if (contentsStart.test(lines[i])) {
break;
}
}
if (i == lines.length) {
throw Error(`in ${f}: ran out of lines looking for start of ToC`);
}
i++;
out.push(''); // blank line before ToC
// Generate the ToC
let toc = generateGfmToc(contents, gfmOpts);
// Delete any patterns in tocDelete from the ToC
for (pat of tocDelete) {
if (pat.test(toc[0])) {
toc = toc.splice(1); // delete first entry
}
}
// Push the whole ToC out
out.push(toc.join('\n'));
out.push('');
// Now, look for the end of the old ToC
// (the next section following the old ToC)
for (; i < lines.length; i++) {
if (contentsEnd.test(lines[i])) {
break;
}
}
if (i == lines.length) {
throw Error(`in ${f}: ran out of lines looking for end of ToC`);
}
const oldcopyright = /(Copyright\s*[©]?)\s*([0-9]{4,4})[–-—](?:[0-9]{4,4})\s*Unicode/;
const newyear = new Date().getFullYear(); // 2023, etc
const badlink = /(\()(http[s]?:\/\/[w\.]*unicode\.org\/reports\/tr35\/)?tr35([^\./]*)\.html/g;
const badlink2 = /(\()(http[s]?:\/\/[w\.]*unicode\.org\/reports\/tr35)[\/]?#/g;
const badlink3 = /\(http(?:s)?:\/\/(?:www\.)?unicode\.org\/reports\/tr35(?:\/)?\)/g;
// Write out all remaining lines in the file.
for (; i < lines.length; i++) {
out.push(lines[i]
.replace(oldcopyright, `$1 $2${newyear} Unicode`)
.replace(badlink, '$1tr35$3.md')
.replace(badlink2, '$1tr35.md#')
.replace(badlink3, '(tr35.md)'));
}
// Write the whole file to disk.
await fs.writeFile(f, out.join('\n'), 'utf-8');
return {
name: path.basename(f),
lines: out.length,
toclines: toc.length
};
}
// Process everything.
getSrcFiles()
.then(f => Promise.all(f.map(p => processFile(p))))
.then(x => console.dir(x), console.error);