From 7bf08e3706855ae8fea3e95c58ea5f37fae33ab5 Mon Sep 17 00:00:00 2001 From: David Evans Date: Wed, 9 May 2018 21:16:13 +0100 Subject: [PATCH] Render apple-touch-icon automatically --- bin/generate-screenshots.js | 83 ++++++++++++++++++++++------- web/resources/apple-touch-icon.png | Bin 3268 -> 10054 bytes 2 files changed, 64 insertions(+), 19 deletions(-) diff --git a/bin/generate-screenshots.js b/bin/generate-screenshots.js index d95ffc3..f78e311 100755 --- a/bin/generate-screenshots.js +++ b/bin/generate-screenshots.js @@ -5,6 +5,22 @@ const buffer2stream = require('buffer-to-stream'); const fs = require('fs'); const PngCrush = require('pngcrush'); const svg2png = require('svg2png'); +const util = require('util'); + +const readFile = util.promisify(fs.readFile); +const writeFile = util.promisify(fs.writeFile); + +function make(parent, tag, attrs = {}) { + const doc = parent.ownerDocument; + const element = doc.createElement(tag); + for(const k in attrs) { + if(Object.prototype.hasOwnProperty.call(attrs, k)) { + element.setAttribute(k, attrs[k]); + } + } + parent.appendChild(element); + return element; +} function read(pipe) { return new Promise((resolve) => { @@ -31,15 +47,7 @@ function processError(err) { function getReadmeFile() { if(process.argv.length > 2 && process.argv[2] !== '-') { - return new Promise((resolve, reject) => { - fs.readFile(process.argv[2], (err, data) => { - if(err) { - reject(err); - } else { - resolve(data); - } - }); - }); + return readFile(process.argv[2]); } else { process.stdin.setEncoding('utf8'); return read(process.stdin); @@ -84,6 +92,47 @@ function findSamples(content) { * }); */ + results.push({ + code: ( + 'theme monospace\n' + + 'begin A, B\n' + + 'A -> B: sequence\n' + + 'B -> A: diagram\n' + ), + file: 'web/resources/apple-touch-icon.png', + mutator: (diagram) => { + const base = diagram.dom(); + const [defs] = base.getElementsByTagName('defs'); + const grad = make(defs, 'linearGradient', { + 'id': 'background', + 'x1': 0, + 'x2': 0, + 'y1': 0.1, + 'y2': 0.9, + }); + make(grad, 'stop', {'offset': '0%', 'stop-color': '#9BCDFD'}); + make(grad, 'stop', {'offset': '100%', 'stop-color': '#8BC2FF'}); + + const offset = 5; + const size = diagram.getSize(); + const fill = make(base, 'rect', { + 'fill': 'url(#background)', + 'height': size.height * 1.2, + 'width': size.width * 1.2, + 'x': -offset - size.width * 0.1, + 'y': -offset - size.height * 0.1, + }); + base.insertBefore(fill, base.firstChild); + + for(const txt of base.getElementsByTagName('text')) { + const sz = txt.getAttribute('font-size'); + txt.setAttribute('font-size', sz * 1.2); + txt.setAttribute('font-family', 'courier'); + } + }, + size: {height: 432, width: 432}, + }); + return results; } @@ -102,7 +151,7 @@ function compressImageBuffer(buffer) { return stream2buffer(compressed); } -function renderSample({file, code, size}) { +function renderSample({file, code, mutator, size}) { process.stdout.write('generating ' + file + '\n'); const diagram = new VirtualSequenceDiagram(code); @@ -117,18 +166,14 @@ function renderSample({file, code, size}) { height = diagram.getSize().height * RESOLUTION; } + if(mutator) { + mutator(diagram); + } + return diagram.getSVGCode() .then((svg) => svg2png(svg, {height, width})) .then(compressImageBuffer) - .then((buffer) => new Promise((resolve, reject) => { - fs.writeFile(file, buffer, {mode: 0o644}, (err) => { - if(err) { - reject(err); - } else { - resolve(); - } - }); - })) + .then((buffer) => writeFile(file, buffer, {mode: 0o644})) .then(() => process.stdout.write(file + ' complete\n')) .catch((err) => process.stderr.write( 'Failed to generate ' + file + ': ' + diff --git a/web/resources/apple-touch-icon.png b/web/resources/apple-touch-icon.png index 718f201a5e29172a0d48c2b7c93ef946c22df29e..10f5f3d5188df645c6119ce26445288c062cd993 100644 GIT binary patch literal 10054 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 Zzb5ATQE|Ik;C&oOU)T6@$=~1){|C|NVf_FA literal 3268 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