diff --git a/package.json b/package.json index e50160e..90e2343 100644 --- a/package.json +++ b/package.json @@ -29,6 +29,7 @@ "nomnom": "^1.8.1", "pako": "1.0.4", "selenium-webdriver": "^2.48.2", + "sri-toolbox": "^0.2.0", "uglify-js": "~2.7.5" }, "bin": "cli.js", diff --git a/release.sh b/release.sh index 177cdf8..90a931d 100755 --- a/release.sh +++ b/release.sh @@ -112,6 +112,10 @@ git add .gitignore dist/ sed -i.bak -E 's|"version": "[^"]+",|"version": "'$VERSION'",|' package.json rm -f package.json.bak +# Update the version number in CDN URLs included in the README files, +# and regenerate the Subresource Integrity hash for these files. +node update-sri.js "${VERSION}" README.md contrib/*/README.md + # Make the commit and tag, and push them. git add package.json bower.json git commit -n -m "v$VERSION" @@ -129,6 +133,10 @@ if [ ! -z "$NEXT_VERSION" ]; then sed -i.bak -E 's|"version": "[^"]+",|"version": "'$NEXT_VERSION'-pre",|' package.json rm -f package.json.bak + # Refer to the just-released version in the documentation of the + # development branch, too. Most people will read docs on master. + node update-sri.js "${VERSION}" README.md contrib/*/README.md + git add package.json bower.json git commit -n -m "Bump master to v$NEXT_VERSION-pre" git push origin "$BRANCH" diff --git a/update-sri.js b/update-sri.js new file mode 100644 index 0000000..3a2c8d6 --- /dev/null +++ b/update-sri.js @@ -0,0 +1,49 @@ +const fs = require("fs"); +const path = require("path"); +const sriToolbox = require("sri-toolbox"); + +const version = process.argv[2]; + +function read(file, encoding) { + return new Promise((resolve, reject) => + fs.readFile(file, encoding, (err, body) => + err ? reject(err) : resolve(body))); +} + +function write(file, data) { + return new Promise((resolve, reject) => + fs.writeFile(file, data, (err) => + err ? reject(err) : resolve())); +} + +Promise.all(process.argv.slice(3).map(file => + read(file, "utf8") + .then(body => { + // 1 - url prefix: "http…/KaTeX/ + // 2 - opening quote: " + // 3 - preserved suffix: /katex.min.js" integrity="…" + // 4 - file name: katex.min.js + // 5 - integrity opening quote: " + // 6 - old hash: sha384-… + // 7 - integrity hash algorithm: sha384 + const re = /((["'])https?:\/\/cdnjs.cloudflare.com\/ajax\/libs\/KaTeX\/)[^\/"']+(\/([^"']+)\2(?:\s+integrity=(["'])(([^-]+)-[^"']+)\5)?)/g; + const hashes = {}; + body = body.replace(re, (m, pre, oq1, post, file, oq2, old, algo) => { + if (old) { + hashes[old] = { file, algo }; + } + return pre + version + post; + }); + return Promise.all(Object.keys(hashes).map(hash => + read(path.join("dist", hashes[hash].file), null) + .then(data => { + body = body.replace(hash, sriToolbox.generate({ + algorithms: [hashes[hash].algo], + }, data)); + }) + )).then(() => write(file, body)); + }) +)).then(() => process.exit(0), err => { + console.error(err.stack); + process.exit(1); +});