"use strict";
const path = require("path");
const fs = require("fs-extra");
const semver = require("semver");
const ChangeFileDir = path.join(__dirname, "../changes");
const ModifiedSinceVersion = "2.x";
const Version = process.argv[2];
class Output {
constructor() {
this.buffer = "";
}
log(...s) {
this.buffer += s.join("") + "\n";
}
}
async function main() {
const out = new Output();
await GenerateChangeList(out);
await CopyMarkdown(out, "packages-desc.md");
await GeneratePackageList(out);
await CopyMarkdown(out, "style-set-sample-image.md");
await CopyMarkdown(out, "deprecated-packages.md");
await fs.ensureDir(path.join(__dirname, `../release-archives/`));
await fs.writeFile(
path.join(__dirname, `../release-archives/release-notes-${Version}.md`),
out.buffer
);
}
main().catch(e => {
console.error(e);
process.exit(1);
});
///////////////////////////////////////////////////////////////////////////////////////////////////
// Copy Markdown
async function CopyMarkdown(out, name) {
const content = await fs.readFile(
path.resolve(__dirname, `release-note-fragments/${name}`),
"utf8"
);
out.log(content);
}
///////////////////////////////////////////////////////////////////////////////////////////////////
// CHANGE LIST
async function GenerateChangeList(out) {
const changeFiles = await fs.readdir(ChangeFileDir);
const fragments = new Map();
for (const file of changeFiles) {
const filePath = path.join(ChangeFileDir, file);
const fileParts = path.parse(filePath);
if (fileParts.ext !== ".md") continue;
if (!semver.valid(fileParts.name) || semver.lt(Version, fileParts.name)) continue;
fragments.set(fileParts.name, await fs.readFile(filePath, "utf8"));
}
const sortedFragments = Array.from(fragments).sort((a, b) => semver.compare(b[0], a[0]));
out.log(`## Modifications since version ${ModifiedSinceVersion}`);
for (const [version, notes] of sortedFragments) {
out.log(` * **${version}**`);
out.log((notes.trim() + "\n").replace(/^/gm, " "));
}
}
///////////////////////////////////////////////////////////////////////////////////////////////////
// PACKAGE LIST
const PackageShapes = {
// shapeDesc, shapeNameSuffix, slab, count, nospace
"": ["Default", "", false, true],
slab: ["Slab", "Slab", true, true],
curly: ["Curly", "Curly", false, true],
"curly-slab": ["Curly Slab", "Curly Slab", true, true],
ss01: ["Andale Mono Style", "SS01"],
ss02: ["Anonymous Pro Style", "SS02"],
ss03: ["Consolas Style", "SS03"],
ss04: ["Menlo Style", "SS04"],
ss05: ["Fira Mono Style", "SS05"],
ss06: ["Liberation Mono Style", "SS06"],
ss07: ["Monaco Style", "SS07"],
ss08: ["Pragmata Pro Style", "SS08"],
ss09: ["Source Code Pro Style", "SS09"],
ss10: ["Envy Code R Style", "SS10"],
ss11: ["X Windows Fixed Style", "SS11"],
ss12: ["Ubuntu Mono Style", "SS12"],
aile: ["Quasi-proportional", "Aile", false, false, true],
etoile: ["Quasi-proportional slab-serif", "Etoile", false, false, true],
sparkle: ["Quasi-proportional family — like iA Writer’s Duo.", "Sparkle", false, false, true]
};
const PackageSpacings = {
// spacingDesc, ligation, spacingNameSuffix
"": ["Default", true, ""],
term: ["Terminal", false, "Type"],
type: ["Typesetting", true, "Type"],
"term-lig": ["Terminal-Ligature", true, "TermLig"]
};
async function GeneratePackageList(out) {
let nr = 1;
out.log(`### Packages`);
out.log(`| Package | Description |\n| --- | --- |`);
for (let shape in PackageShapes) {
const [shapeDesc, shapeNameSuffix, , count, nospace] = PackageShapes[shape];
for (let spacing in PackageSpacings) {
if (nospace && spacing) continue;
const [spacingDesc, ligation, spacingNameSuffix] = PackageSpacings[spacing];
const fileName = buildName(
"-",
count ? pad(nr, 2, "0") : "",
"iosevka",
spacing,
shape,
Version
);
const familyName = buildName(" ", "Iosevka", spacingNameSuffix, shapeNameSuffix);
const desc = nospace
? `_${shapeDesc}_`
: `**Shape**: _${shapeDesc}_; **Spacing**: _${spacingDesc}_
` +
`**Ligation**: ${flag(ligation)}`;
if (count) nr++;
out.log(`| \`${fileName}\`
**Menu Name**: \`${familyName}\` | ${desc} |`);
}
}
out.log();
}
function pad(s, n, p) {
s = "" + s;
while (s.length < n) s = p + s;
return s;
}
function buildName(j, ...parts) {
return parts.filter(x => !!x).join(j);
}
function flag(f) {
return f ? "**Yes**" : "No";
}