├── design ├── n5.png ├── icon.pxm ├── sakura.png ├── tree3.pxm ├── icon-tree.pxm ├── fonts │ ├── titilliumweb-light-webfont.eot │ ├── titilliumweb-light-webfont.ttf │ ├── titilliumweb-light-webfont.woff │ ├── titilliumweb-light-webfont.woff2 │ ├── titilliumweb-extralight-webfont.eot │ ├── titilliumweb-extralight-webfont.ttf │ ├── titilliumweb-semibold-webfont.eot │ ├── titilliumweb-semibold-webfont.ttf │ ├── titilliumweb-semibold-webfont.woff │ ├── titilliumweb-semibold-webfont.woff2 │ ├── titilliumweb-extralight-webfont.woff │ ├── titilliumweb-extralight-webfont.woff2 │ ├── titilliumweb-lightitalic-webfont.eot │ ├── titilliumweb-lightitalic-webfont.ttf │ ├── titilliumweb-lightitalic-webfont.woff │ ├── titilliumweb-lightitalic-webfont.woff2 │ ├── titilliumweb-semibolditalic-webfont.eot │ ├── titilliumweb-semibolditalic-webfont.ttf │ ├── titilliumweb-semibolditalic-webfont.woff │ ├── titilliumweb-semibolditalic-webfont.woff2 │ └── fonts.css ├── hardy.css ├── index.html ├── bug.svg ├── design.html └── randomColor.js ├── site ├── icon.png ├── projects │ ├── piano-roll │ │ ├── project.json │ │ └── index.html │ └── index.html ├── fonts │ ├── titilliumweb-light-webfont.eot │ ├── titilliumweb-light-webfont.ttf │ ├── titilliumweb-light-webfont.woff │ ├── titilliumweb-light-webfont.woff2 │ ├── titilliumweb-semibold-webfont.eot │ ├── titilliumweb-semibold-webfont.ttf │ ├── titilliumweb-semibold-webfont.woff │ ├── titilliumweb-extralight-webfont.eot │ ├── titilliumweb-extralight-webfont.ttf │ ├── titilliumweb-extralight-webfont.woff │ ├── titilliumweb-extralight-webfont.woff2 │ ├── titilliumweb-lightitalic-webfont.eot │ ├── titilliumweb-lightitalic-webfont.ttf │ ├── titilliumweb-lightitalic-webfont.woff │ ├── titilliumweb-semibold-webfont.woff2 │ ├── titilliumweb-lightitalic-webfont.woff2 │ ├── titilliumweb-semibolditalic-webfont.eot │ ├── titilliumweb-semibolditalic-webfont.ttf │ ├── titilliumweb-semibolditalic-webfont.woff │ └── titilliumweb-semibolditalic-webfont.woff2 ├── img │ ├── bug.svg │ └── tree.svg ├── index.html ├── about │ └── index.html ├── css │ └── etiologies.css └── js │ ├── leaves.min.js │ └── leaves.js ├── content ├── icon.png ├── projects │ ├── piano-roll │ │ ├── project.json │ │ ├── ui.js │ │ └── index.html │ └── index.html ├── fonts │ ├── titilliumweb-light-webfont.eot │ ├── titilliumweb-light-webfont.ttf │ ├── titilliumweb-light-webfont.woff │ ├── titilliumweb-light-webfont.woff2 │ ├── titilliumweb-semibold-webfont.eot │ ├── titilliumweb-semibold-webfont.ttf │ ├── titilliumweb-semibold-webfont.woff │ ├── titilliumweb-extralight-webfont.eot │ ├── titilliumweb-extralight-webfont.ttf │ ├── titilliumweb-extralight-webfont.woff │ ├── titilliumweb-lightitalic-webfont.eot │ ├── titilliumweb-lightitalic-webfont.ttf │ ├── titilliumweb-semibold-webfont.woff2 │ ├── titilliumweb-extralight-webfont.woff2 │ ├── titilliumweb-lightitalic-webfont.woff │ ├── titilliumweb-lightitalic-webfont.woff2 │ ├── titilliumweb-semibolditalic-webfont.eot │ ├── titilliumweb-semibolditalic-webfont.ttf │ ├── titilliumweb-semibolditalic-webfont.woff │ └── titilliumweb-semibolditalic-webfont.woff2 ├── index.html ├── img │ ├── bug.svg │ └── tree.svg └── about │ └── index.html ├── rsync.sh ├── tools ├── _DO-NOT-EDIT_.md ├── utils │ └── rel.js ├── tasks │ ├── copy-tree.js │ ├── copy-static.js │ ├── source-tree.js │ ├── build-project.js │ └── process-html.js └── build-site.js ├── tools-src ├── utils │ └── rel.js ├── tasks │ ├── copy-tree.js │ ├── copy-static.js │ ├── source-tree.js │ ├── build-project.js │ └── process-html.js └── build-site.js ├── README.md ├── client-src └── leaves.js ├── .gitignore ├── LICENSE ├── package.json ├── css ├── etiologies.css └── fonts.css └── TODO.txt /design/n5.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/darobin/etiologi.es/master/design/n5.png -------------------------------------------------------------------------------- /site/icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/darobin/etiologi.es/master/site/icon.png -------------------------------------------------------------------------------- /design/icon.pxm: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/darobin/etiologi.es/master/design/icon.pxm -------------------------------------------------------------------------------- /content/icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/darobin/etiologi.es/master/content/icon.png -------------------------------------------------------------------------------- /design/sakura.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/darobin/etiologi.es/master/design/sakura.png -------------------------------------------------------------------------------- /design/tree3.pxm: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/darobin/etiologi.es/master/design/tree3.pxm -------------------------------------------------------------------------------- /site/projects/piano-roll/project.json: -------------------------------------------------------------------------------- 1 | 2 | { 3 | "browserify": ["ui.js"] 4 | } 5 | 6 | -------------------------------------------------------------------------------- /content/projects/piano-roll/project.json: -------------------------------------------------------------------------------- 1 | 2 | { 3 | "browserify": ["ui.js"] 4 | } 5 | 6 | -------------------------------------------------------------------------------- /design/icon-tree.pxm: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/darobin/etiologi.es/master/design/icon-tree.pxm -------------------------------------------------------------------------------- /rsync.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | rsync -avze ssh /Projects/etiologi.es/site/ robin@$POLITY:/var/www/sites/etiologi.es/public/ 3 | -------------------------------------------------------------------------------- /design/fonts/titilliumweb-light-webfont.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/darobin/etiologi.es/master/design/fonts/titilliumweb-light-webfont.eot -------------------------------------------------------------------------------- /design/fonts/titilliumweb-light-webfont.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/darobin/etiologi.es/master/design/fonts/titilliumweb-light-webfont.ttf -------------------------------------------------------------------------------- /site/fonts/titilliumweb-light-webfont.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/darobin/etiologi.es/master/site/fonts/titilliumweb-light-webfont.eot -------------------------------------------------------------------------------- /site/fonts/titilliumweb-light-webfont.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/darobin/etiologi.es/master/site/fonts/titilliumweb-light-webfont.ttf -------------------------------------------------------------------------------- /site/fonts/titilliumweb-light-webfont.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/darobin/etiologi.es/master/site/fonts/titilliumweb-light-webfont.woff -------------------------------------------------------------------------------- /site/fonts/titilliumweb-light-webfont.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/darobin/etiologi.es/master/site/fonts/titilliumweb-light-webfont.woff2 -------------------------------------------------------------------------------- /content/fonts/titilliumweb-light-webfont.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/darobin/etiologi.es/master/content/fonts/titilliumweb-light-webfont.eot -------------------------------------------------------------------------------- /content/fonts/titilliumweb-light-webfont.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/darobin/etiologi.es/master/content/fonts/titilliumweb-light-webfont.ttf -------------------------------------------------------------------------------- /content/fonts/titilliumweb-light-webfont.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/darobin/etiologi.es/master/content/fonts/titilliumweb-light-webfont.woff -------------------------------------------------------------------------------- /design/fonts/titilliumweb-light-webfont.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/darobin/etiologi.es/master/design/fonts/titilliumweb-light-webfont.woff -------------------------------------------------------------------------------- /design/fonts/titilliumweb-light-webfont.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/darobin/etiologi.es/master/design/fonts/titilliumweb-light-webfont.woff2 -------------------------------------------------------------------------------- /site/fonts/titilliumweb-semibold-webfont.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/darobin/etiologi.es/master/site/fonts/titilliumweb-semibold-webfont.eot -------------------------------------------------------------------------------- /site/fonts/titilliumweb-semibold-webfont.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/darobin/etiologi.es/master/site/fonts/titilliumweb-semibold-webfont.ttf -------------------------------------------------------------------------------- /site/fonts/titilliumweb-semibold-webfont.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/darobin/etiologi.es/master/site/fonts/titilliumweb-semibold-webfont.woff -------------------------------------------------------------------------------- /content/fonts/titilliumweb-light-webfont.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/darobin/etiologi.es/master/content/fonts/titilliumweb-light-webfont.woff2 -------------------------------------------------------------------------------- /content/fonts/titilliumweb-semibold-webfont.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/darobin/etiologi.es/master/content/fonts/titilliumweb-semibold-webfont.eot -------------------------------------------------------------------------------- /content/fonts/titilliumweb-semibold-webfont.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/darobin/etiologi.es/master/content/fonts/titilliumweb-semibold-webfont.ttf -------------------------------------------------------------------------------- /content/fonts/titilliumweb-semibold-webfont.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/darobin/etiologi.es/master/content/fonts/titilliumweb-semibold-webfont.woff -------------------------------------------------------------------------------- /design/fonts/titilliumweb-extralight-webfont.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/darobin/etiologi.es/master/design/fonts/titilliumweb-extralight-webfont.eot -------------------------------------------------------------------------------- /design/fonts/titilliumweb-extralight-webfont.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/darobin/etiologi.es/master/design/fonts/titilliumweb-extralight-webfont.ttf -------------------------------------------------------------------------------- /design/fonts/titilliumweb-semibold-webfont.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/darobin/etiologi.es/master/design/fonts/titilliumweb-semibold-webfont.eot -------------------------------------------------------------------------------- /design/fonts/titilliumweb-semibold-webfont.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/darobin/etiologi.es/master/design/fonts/titilliumweb-semibold-webfont.ttf -------------------------------------------------------------------------------- /design/fonts/titilliumweb-semibold-webfont.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/darobin/etiologi.es/master/design/fonts/titilliumweb-semibold-webfont.woff -------------------------------------------------------------------------------- /design/fonts/titilliumweb-semibold-webfont.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/darobin/etiologi.es/master/design/fonts/titilliumweb-semibold-webfont.woff2 -------------------------------------------------------------------------------- /site/fonts/titilliumweb-extralight-webfont.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/darobin/etiologi.es/master/site/fonts/titilliumweb-extralight-webfont.eot -------------------------------------------------------------------------------- /site/fonts/titilliumweb-extralight-webfont.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/darobin/etiologi.es/master/site/fonts/titilliumweb-extralight-webfont.ttf -------------------------------------------------------------------------------- /site/fonts/titilliumweb-extralight-webfont.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/darobin/etiologi.es/master/site/fonts/titilliumweb-extralight-webfont.woff -------------------------------------------------------------------------------- /site/fonts/titilliumweb-extralight-webfont.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/darobin/etiologi.es/master/site/fonts/titilliumweb-extralight-webfont.woff2 -------------------------------------------------------------------------------- /site/fonts/titilliumweb-lightitalic-webfont.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/darobin/etiologi.es/master/site/fonts/titilliumweb-lightitalic-webfont.eot -------------------------------------------------------------------------------- /site/fonts/titilliumweb-lightitalic-webfont.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/darobin/etiologi.es/master/site/fonts/titilliumweb-lightitalic-webfont.ttf -------------------------------------------------------------------------------- /site/fonts/titilliumweb-lightitalic-webfont.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/darobin/etiologi.es/master/site/fonts/titilliumweb-lightitalic-webfont.woff -------------------------------------------------------------------------------- /site/fonts/titilliumweb-semibold-webfont.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/darobin/etiologi.es/master/site/fonts/titilliumweb-semibold-webfont.woff2 -------------------------------------------------------------------------------- /content/fonts/titilliumweb-extralight-webfont.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/darobin/etiologi.es/master/content/fonts/titilliumweb-extralight-webfont.eot -------------------------------------------------------------------------------- /content/fonts/titilliumweb-extralight-webfont.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/darobin/etiologi.es/master/content/fonts/titilliumweb-extralight-webfont.ttf -------------------------------------------------------------------------------- /content/fonts/titilliumweb-extralight-webfont.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/darobin/etiologi.es/master/content/fonts/titilliumweb-extralight-webfont.woff -------------------------------------------------------------------------------- /content/fonts/titilliumweb-lightitalic-webfont.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/darobin/etiologi.es/master/content/fonts/titilliumweb-lightitalic-webfont.eot -------------------------------------------------------------------------------- /content/fonts/titilliumweb-lightitalic-webfont.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/darobin/etiologi.es/master/content/fonts/titilliumweb-lightitalic-webfont.ttf -------------------------------------------------------------------------------- /content/fonts/titilliumweb-semibold-webfont.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/darobin/etiologi.es/master/content/fonts/titilliumweb-semibold-webfont.woff2 -------------------------------------------------------------------------------- /design/fonts/titilliumweb-extralight-webfont.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/darobin/etiologi.es/master/design/fonts/titilliumweb-extralight-webfont.woff -------------------------------------------------------------------------------- /design/fonts/titilliumweb-extralight-webfont.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/darobin/etiologi.es/master/design/fonts/titilliumweb-extralight-webfont.woff2 -------------------------------------------------------------------------------- /design/fonts/titilliumweb-lightitalic-webfont.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/darobin/etiologi.es/master/design/fonts/titilliumweb-lightitalic-webfont.eot -------------------------------------------------------------------------------- /design/fonts/titilliumweb-lightitalic-webfont.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/darobin/etiologi.es/master/design/fonts/titilliumweb-lightitalic-webfont.ttf -------------------------------------------------------------------------------- /design/fonts/titilliumweb-lightitalic-webfont.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/darobin/etiologi.es/master/design/fonts/titilliumweb-lightitalic-webfont.woff -------------------------------------------------------------------------------- /site/fonts/titilliumweb-lightitalic-webfont.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/darobin/etiologi.es/master/site/fonts/titilliumweb-lightitalic-webfont.woff2 -------------------------------------------------------------------------------- /site/fonts/titilliumweb-semibolditalic-webfont.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/darobin/etiologi.es/master/site/fonts/titilliumweb-semibolditalic-webfont.eot -------------------------------------------------------------------------------- /site/fonts/titilliumweb-semibolditalic-webfont.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/darobin/etiologi.es/master/site/fonts/titilliumweb-semibolditalic-webfont.ttf -------------------------------------------------------------------------------- /content/fonts/titilliumweb-extralight-webfont.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/darobin/etiologi.es/master/content/fonts/titilliumweb-extralight-webfont.woff2 -------------------------------------------------------------------------------- /content/fonts/titilliumweb-lightitalic-webfont.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/darobin/etiologi.es/master/content/fonts/titilliumweb-lightitalic-webfont.woff -------------------------------------------------------------------------------- /content/fonts/titilliumweb-lightitalic-webfont.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/darobin/etiologi.es/master/content/fonts/titilliumweb-lightitalic-webfont.woff2 -------------------------------------------------------------------------------- /content/fonts/titilliumweb-semibolditalic-webfont.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/darobin/etiologi.es/master/content/fonts/titilliumweb-semibolditalic-webfont.eot -------------------------------------------------------------------------------- /content/fonts/titilliumweb-semibolditalic-webfont.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/darobin/etiologi.es/master/content/fonts/titilliumweb-semibolditalic-webfont.ttf -------------------------------------------------------------------------------- /design/fonts/titilliumweb-lightitalic-webfont.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/darobin/etiologi.es/master/design/fonts/titilliumweb-lightitalic-webfont.woff2 -------------------------------------------------------------------------------- /design/fonts/titilliumweb-semibolditalic-webfont.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/darobin/etiologi.es/master/design/fonts/titilliumweb-semibolditalic-webfont.eot -------------------------------------------------------------------------------- /design/fonts/titilliumweb-semibolditalic-webfont.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/darobin/etiologi.es/master/design/fonts/titilliumweb-semibolditalic-webfont.ttf -------------------------------------------------------------------------------- /design/fonts/titilliumweb-semibolditalic-webfont.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/darobin/etiologi.es/master/design/fonts/titilliumweb-semibolditalic-webfont.woff -------------------------------------------------------------------------------- /site/fonts/titilliumweb-semibolditalic-webfont.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/darobin/etiologi.es/master/site/fonts/titilliumweb-semibolditalic-webfont.woff -------------------------------------------------------------------------------- /site/fonts/titilliumweb-semibolditalic-webfont.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/darobin/etiologi.es/master/site/fonts/titilliumweb-semibolditalic-webfont.woff2 -------------------------------------------------------------------------------- /content/fonts/titilliumweb-semibolditalic-webfont.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/darobin/etiologi.es/master/content/fonts/titilliumweb-semibolditalic-webfont.woff -------------------------------------------------------------------------------- /content/fonts/titilliumweb-semibolditalic-webfont.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/darobin/etiologi.es/master/content/fonts/titilliumweb-semibolditalic-webfont.woff2 -------------------------------------------------------------------------------- /design/fonts/titilliumweb-semibolditalic-webfont.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/darobin/etiologi.es/master/design/fonts/titilliumweb-semibolditalic-webfont.woff2 -------------------------------------------------------------------------------- /tools/_DO-NOT-EDIT_.md: -------------------------------------------------------------------------------- 1 | 2 | # WARNING - DO NOT EDIT 3 | 4 | All the code under this directory (`tools`) is generated from the code in `tools-src`. Any change 5 | will be lost. 6 | -------------------------------------------------------------------------------- /tools-src/utils/rel.js: -------------------------------------------------------------------------------- 1 | 2 | var jn = require("path").join; 3 | 4 | module.exports = function (root) { 5 | return function (to) { 6 | return jn(root, to); 7 | } 8 | }; 9 | -------------------------------------------------------------------------------- /tools/utils/rel.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | var jn = require("path").join; 4 | 5 | module.exports = function (root) { 6 | return function (to) { 7 | return jn(root, to); 8 | }; 9 | }; -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # etiologi.es 2 | 3 | Philosophical tinkering. 4 | 5 | 6 | ## Build set up 7 | 8 | If you run `npm run build` (or `npm run watch`, which is the same except it keeps building for you 9 | whenever there are changes) the whole system gets built. This involves: 10 | 11 | 1. Converting all the ES6 in `tools-src` to ES5 in `tools`. 12 | 13 | -------------------------------------------------------------------------------- /content/projects/piano-roll/ui.js: -------------------------------------------------------------------------------- 1 | 2 | let $ = require("jquery") 3 | , $mode = $("#mode") 4 | , $critical = $("#critical") 5 | , $size = $("#size") 6 | , $run = $("#run") 7 | , $dropLine = $("#drop-line") 8 | , $latticeLine = $("#lattice-line") 9 | , $pianoRoll = $("#piano-roll") 10 | ; 11 | 12 | console.log("OMG it works!", $size.val()); 13 | -------------------------------------------------------------------------------- /content/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Tinkering with Natural Philosophy 6 | 7 | 8 |

9 | Welcome to Etiologies! You can read more about the project. There is 10 | very little content at the moment; it will grow over time. 11 |

12 | 13 | 14 | -------------------------------------------------------------------------------- /tools-src/tasks/copy-tree.js: -------------------------------------------------------------------------------- 1 | 2 | let fs = require("fs-extra") 3 | , jn = require("path").join 4 | ; 5 | 6 | function makeDir (dir) { 7 | return new Promise((resolve, reject) => { 8 | fs.mkdirp(dir, (err) => { 9 | if (err) return reject(); 10 | resolve(); 11 | }); 12 | }); 13 | } 14 | 15 | // build the output tree 16 | module.exports = function (targetDir, tree) { 17 | var proms = []; 18 | for (let k in tree) if (tree[k].isDirectory()) proms.push(makeDir(jn(targetDir, k))); 19 | return Promise.all(proms); 20 | }; 21 | -------------------------------------------------------------------------------- /tools/tasks/copy-tree.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | var fs = require("fs-extra"), 4 | jn = require("path").join; 5 | 6 | function makeDir(dir) { 7 | return new Promise(function (resolve, reject) { 8 | fs.mkdirp(dir, function (err) { 9 | if (err) return reject(); 10 | resolve(); 11 | }); 12 | }); 13 | } 14 | 15 | // build the output tree 16 | module.exports = function (targetDir, tree) { 17 | var proms = []; 18 | for (var k in tree) { 19 | if (tree[k].isDirectory()) proms.push(makeDir(jn(targetDir, k))); 20 | }return Promise.all(proms); 21 | }; -------------------------------------------------------------------------------- /client-src/leaves.js: -------------------------------------------------------------------------------- 1 | 2 | let randomColor = require("randomcolor") 3 | , leaves = document.querySelectorAll("g > path:not(.bark)") 4 | , barks = document.querySelectorAll("path.bark") 5 | // hue: red, orange, yellow, green, blue, purple, pink, monochrome 6 | // luminosity: light 7 | , colours = randomColor({ hue: "green", count: leaves.length }) 8 | , barkColours = randomColor({ hue: "orange", count: barks.length }) 9 | ; 10 | for (let i = 0, n = leaves.length; i < n; i++) 11 | leaves[i].setAttributeNS(null, "fill", colours[i]); 12 | for (let i = 0, n = barks.length; i < n; i++) 13 | barks[i].setAttributeNS(null, "fill", barkColours[i]); 14 | -------------------------------------------------------------------------------- /tools-src/tasks/copy-static.js: -------------------------------------------------------------------------------- 1 | 2 | let fs = require("fs-extra") 3 | , jn = require("path").join 4 | , ext = require("path").extname 5 | ; 6 | 7 | function copyStatic (from, to) { 8 | return new Promise((resolve, reject) => { 9 | fs.copy(from, to, (err) => { 10 | if (err) return reject(); 11 | resolve(); 12 | }); 13 | }); 14 | } 15 | 16 | // build the output tree 17 | module.exports = function (sourceDir, targetDir, tree) { 18 | var proms = []; 19 | for (let k in tree) 20 | if (!tree[k].isDirectory() && ext(k) !== ".html") 21 | proms.push(copyStatic(jn(sourceDir, k), jn(targetDir, k))); 22 | return Promise.all(proms); 23 | }; 24 | -------------------------------------------------------------------------------- /tools/tasks/copy-static.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | var fs = require("fs-extra"), 4 | jn = require("path").join, 5 | ext = require("path").extname; 6 | 7 | function copyStatic(from, to) { 8 | return new Promise(function (resolve, reject) { 9 | fs.copy(from, to, function (err) { 10 | if (err) return reject(); 11 | resolve(); 12 | }); 13 | }); 14 | } 15 | 16 | // build the output tree 17 | module.exports = function (sourceDir, targetDir, tree) { 18 | var proms = []; 19 | for (var k in tree) { 20 | if (!tree[k].isDirectory() && ext(k) !== ".html") proms.push(copyStatic(jn(sourceDir, k), jn(targetDir, k))); 21 | }return Promise.all(proms); 22 | }; -------------------------------------------------------------------------------- /content/projects/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Projects 6 | 7 | 8 |

9 | This is a list of all projects developed on this site. Currently, there is only one. 10 |

11 |
12 |
One-Dimensional Avalanche Piano Roll
13 |
14 | This runs avalanches on a one-dimensional lattice (that does not loop around) and 15 | renders them in a piano-roll that shows where they occur in time, the idea being to see if 16 | they might lend themselves to particle analysis. 17 |
18 |
19 | 20 | 21 | -------------------------------------------------------------------------------- /design/hardy.css: -------------------------------------------------------------------------------- 1 | 2 | html, body { 3 | margin: 0; 4 | padding: 0; 5 | font-family: "Roboto Slab"; 6 | font-weight: 300; 7 | min-height: 100vh; 8 | } 9 | 10 | body > header { 11 | background: linear-gradient(to bottom, #ed9d3f, #f5d466); 12 | 13 | } 14 | header > p, header > h1 { 15 | width: 960px; 16 | margin: auto; 17 | } 18 | .site-title { 19 | font-size: 57px; 20 | color: #fff; 21 | text-align: center; 22 | letter-spacing: 38px; 23 | text-shadow: 1px 1px 1px #234; 24 | } 25 | main > header { 26 | background: #fff; 27 | border: 1px solid #0E6764; 28 | } 29 | h1 { 30 | color: #69c093; 31 | font-size: 38px; 32 | font-weight: 300; 33 | } 34 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Logs 2 | logs 3 | *.log 4 | 5 | # Runtime data 6 | pids 7 | *.pid 8 | *.seed 9 | 10 | # Directory for instrumented libs generated by jscoverage/JSCover 11 | lib-cov 12 | 13 | # Coverage directory used by tools like istanbul 14 | coverage 15 | 16 | # Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files) 17 | .grunt 18 | 19 | # Compiled binary addons (http://nodejs.org/api/addons.html) 20 | build/Release 21 | 22 | # Dependency directory 23 | # Commenting this out is preferred by some people, see 24 | # https://www.npmjs.org/doc/misc/npm-faq.html#should-i-check-my-node_modules-folder-into-git- 25 | node_modules 26 | 27 | # Users Environment Variables 28 | .lock-wscript 29 | 30 | # Robin 31 | scratch 32 | -------------------------------------------------------------------------------- /design/index.html: -------------------------------------------------------------------------------- 1 | 2 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | Etiologies — Tinkering with Natural Philosophy 16 | 17 | 18 | 19 |
20 |

Etiologies

21 |
22 |
23 |
24 |

Tinkering with Natural Philosophy

25 |
26 |
27 | 28 | 29 | -------------------------------------------------------------------------------- /tools-src/tasks/source-tree.js: -------------------------------------------------------------------------------- 1 | 2 | let findit = require("findit") 3 | , pth = require("path") 4 | ; 5 | 6 | function norm (root, file) { 7 | return "./" + pth.relative(root, file); 8 | } 9 | 10 | module.exports = function (root) { 11 | return new Promise((resolve, reject) => { 12 | let finder = findit(root) 13 | , tree = {} 14 | ; 15 | finder.on("directory", (file, stat) => { 16 | tree[norm(root, file)] = stat; 17 | }); 18 | finder.on("file", (file, stat) => { 19 | tree[norm(root, file)] = stat; 20 | }); 21 | finder.on("error", (err) => { 22 | finder.stop(); 23 | reject(err); 24 | }); 25 | finder.on("end", () => { 26 | resolve(tree); 27 | }); 28 | }); 29 | }; 30 | -------------------------------------------------------------------------------- /tools/tasks/source-tree.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | var findit = require("findit"), 4 | pth = require("path"); 5 | 6 | function norm(root, file) { 7 | return "./" + pth.relative(root, file); 8 | } 9 | 10 | module.exports = function (root) { 11 | return new Promise(function (resolve, reject) { 12 | var finder = findit(root), 13 | tree = {}; 14 | finder.on("directory", function (file, stat) { 15 | tree[norm(root, file)] = stat; 16 | }); 17 | finder.on("file", function (file, stat) { 18 | tree[norm(root, file)] = stat; 19 | }); 20 | finder.on("error", function (err) { 21 | finder.stop(); 22 | reject(err); 23 | }); 24 | finder.on("end", function () { 25 | resolve(tree); 26 | }); 27 | }); 28 | }; -------------------------------------------------------------------------------- /design/bug.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /site/img/bug.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /content/img/bug.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2015 Robin Berjon 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | 23 | -------------------------------------------------------------------------------- /tools/tasks/build-project.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | var fs = require("fs-extra"), 4 | jn = require("path").join, 5 | bn = require("path").basename, 6 | rel = require("path").resolve, 7 | dn = require("path").dirname, 8 | browserify = require("browserify"), 9 | babelify = require("babelify"); 10 | 11 | function task(cmd, source, target) { 12 | return new Promise(function (resolve, reject) { 13 | browserify(source, { transform: ["babelify"] }).transform(babelify).bundle().on("error", reject).pipe(fs.createWriteStream(target).on("finish", resolve)); 14 | }); 15 | } 16 | 17 | function buildProject(source, target) { 18 | return new Promise(function (resolve, reject) { 19 | fs.readJson(source, function (err, data) { 20 | if (err) return reject(err); 21 | var proms = []; 22 | if (data.browserify) data.browserify.forEach(function (src) { 23 | proms.push(task("browserify", rel(dn(source), src), rel(dn(target), src))); 24 | }); 25 | return Promise.all(proms); 26 | }); 27 | }); 28 | } 29 | 30 | // XXX this is not DRY, we should have it be more generic 31 | module.exports = function (sourceDir, targetDir, tree) { 32 | var proms = []; 33 | for (var k in tree) { 34 | if (!tree[k].isDirectory() && bn(k) === "project.json") proms.push(buildProject(jn(sourceDir, k), jn(targetDir, k))); 35 | }return Promise.all(proms); 36 | }; -------------------------------------------------------------------------------- /tools-src/tasks/build-project.js: -------------------------------------------------------------------------------- 1 | 2 | let fs = require("fs-extra") 3 | , jn = require("path").join 4 | , bn = require("path").basename 5 | , rel = require("path").resolve 6 | , dn = require("path").dirname 7 | , browserify = require("browserify") 8 | , babelify = require("babelify") 9 | ; 10 | 11 | function task (cmd, source, target) { 12 | return new Promise((resolve, reject) => { 13 | browserify(source, { transform: ["babelify"]}) 14 | .transform(babelify) 15 | .bundle() 16 | .on("error", reject) 17 | .pipe(fs.createWriteStream(target).on("finish", resolve)) 18 | ; 19 | }); 20 | } 21 | 22 | function buildProject (source, target) { 23 | return new Promise((resolve, reject) => { 24 | fs.readJson(source, (err, data) => { 25 | if (err) return reject(err); 26 | var proms = []; 27 | if (data.browserify) data.browserify.forEach((src) => { 28 | proms.push(task("browserify", rel(dn(source), src), rel(dn(target), src))); 29 | }); 30 | return Promise.all(proms); 31 | }); 32 | }); 33 | } 34 | 35 | // XXX this is not DRY, we should have it be more generic 36 | module.exports = function (sourceDir, targetDir, tree) { 37 | var proms = []; 38 | for (let k in tree) 39 | if (!tree[k].isDirectory() && bn(k) === "project.json") 40 | proms.push(buildProject(jn(sourceDir, k), jn(targetDir, k))); 41 | return Promise.all(proms); 42 | }; 43 | -------------------------------------------------------------------------------- /content/projects/piano-roll/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | One-Dimensional Avalanche Piano Roll 6 | 7 | 8 |

9 | This project runs avalanches on one-dimensional, non-looping lattice, with varying 10 | parameters. At every time step (when a grain of sand of dropped on the pile), all the 11 | avalanches that take place mark a bar of their extend on a line beneath the lattice, and the 12 | line is moved down. 13 |

14 |

15 | The idea is to see if it lends itself to some sort of analysis at that level. 16 |

17 |
18 |
19 | 20 | 25 |
26 |
27 | 28 | 29 |
30 |
31 | 32 | 33 |
34 |
35 | 36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 | 44 | 45 | 46 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "etiologies", 3 | "version": "0.0.1", 4 | "private": true, 5 | "license": "MIT", 6 | "dependencies": {}, 7 | "devDependencies": { 8 | "async": "1.0.0", 9 | "babel": "^5.2.17", 10 | "babelify": "^6.1.0", 11 | "browserify": "^10.1.3", 12 | "clean-css": "^3.2.10", 13 | "findit": "2.0.0", 14 | "fs-extra": "0.18.4", 15 | "myth": "^1.4.0", 16 | "nodemon": "1.3.7", 17 | "nopt": "3.0.2", 18 | "normalize.css": "^3.0.3", 19 | "randomcolor": "^0.2.0", 20 | "uglify-js": "^2.4.23", 21 | "watchify": "^3.2.1", 22 | "whacko": "0.18.1" 23 | }, 24 | "scripts": { 25 | "build-tools": "babel ./tools-src --out-dir ./tools", 26 | "watch-tools": "nodemon -e js --watch ./tools-src/ --exec 'npm run build-tools'", 27 | "build-css": "cleancss -o ./site/css/etiologies.css ./css/etiologies.css", 28 | "watch-css": "nodemon -e css --watch ./css/ --exec 'npm run build-css'", 29 | "build-js-svg": "browserify ./client-src/leaves.js -o ./site/js/leaves.js && uglifyjs ./site/js/leaves.js -o ./site/js/leaves.min.js", 30 | "build-js": "npm run build-js-svg", 31 | "watch-js": "nodemon -e js --watch ./client-src/ --exec 'npm run build-js'", 32 | "build-site": "node ./tools/build-site.js", 33 | "watch-site": "nodemon -e js,css,html,png,jpg,svg --watch ./tools/ --watch ./content/ --exec 'npm run build-site'", 34 | "build": "npm run build-tools && npm run build-js && npm run build-css && npm run build-site", 35 | "watch": "npm run watch-tools & npm run watch-js & npm run watch-css & npm run watch-site" 36 | }, 37 | "browserify": { 38 | "transform": [ 39 | "babelify" 40 | ] 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /content/about/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | About Etiologies 6 | 7 | 8 |

9 | Etiologies is a web site that is maintained as 10 | an open source project to which anyone 11 | can contribute. Its core goal is to «tinker with natural philosophy» using Web technologies. 12 | It is a broad remit, deliberately. 13 |

14 |

15 | The project’s tenets are: 16 |

17 | 37 |

38 | My primary initial focus is on complexity and criticality, but I’m open to contributions on 39 | other topics as well. 40 |

41 |

42 | I claim no expertise. I am simply having fun and tinkering. 43 |

44 | 45 | 46 | -------------------------------------------------------------------------------- /site/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | Tinkering with Natural Philosophy 4 | 5 |
6 | 7 |

Etiologies

8 | 15 |

Tinkering with Natural Philosophy

16 |

17 | Welcome to Etiologies! You can read more about the project. There is 18 | very little content at the moment; it will grow over time. 19 |

20 | 21 | 22 |
-------------------------------------------------------------------------------- /site/projects/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | Projects 4 | 5 |
6 | 7 |

Etiologies

8 | 15 |

Projects

16 |

17 | This is a list of all projects developed on this site. Currently, there is only one. 18 |

19 |
20 |
One-Dimensional Avalanche Piano Roll
21 |
22 | This runs avalanches on a one-dimensional lattice (that does not loop around) and 23 | renders them in a piano-roll that shows where they occur in time, the idea being to see if 24 | they might lend themselves to particle analysis. 25 |
26 |
27 | 28 | 29 |
-------------------------------------------------------------------------------- /css/etiologies.css: -------------------------------------------------------------------------------- 1 | 2 | @import "../node_modules/normalize.css/normalize.css"; 3 | @import "./fonts.css"; 4 | 5 | body { 6 | font-family: Titillium; 7 | } 8 | iframe { 9 | border: 0; 10 | /* make this %age based */ 11 | } 12 | header { 13 | margin: auto; 14 | max-width: 960px; 15 | } 16 | p.site-title { 17 | text-align: right; 18 | margin: -125px 50px 0 0; 19 | font-size: 50px; 20 | font-weight: 200; 21 | } 22 | nav ul { 23 | list-style-type: none; 24 | text-align: right; 25 | margin: 5px 40px 0 0; 26 | } 27 | nav li { 28 | display: inline-block; 29 | } 30 | nav li a { 31 | display: inline-block; 32 | padding: 0 10px; 33 | line-height: 1; 34 | background: transparent; 35 | } 36 | nav li::before { 37 | content: "・"; 38 | color: silver; 39 | } 40 | nav li:first-of-type::before { 41 | content: none; 42 | } 43 | a { 44 | text-decoration: none; 45 | color: #0e9063; 46 | background: linear-gradient(transparent 0%, transparent 60%, #fff 65%, #fdf3a1 93%, transparent 95%); 47 | } 48 | a:hover { 49 | text-decoration: underline dotted #ff7000; 50 | } 51 | a:active { 52 | color: #ff7000; 53 | } 54 | /* 55 | a[href^="http"]::after { 56 | content: "⇗"; 57 | color: #ff7000; 58 | vertical-align: super; 59 | line-height: 0.5; 60 | } 61 | */ 62 | main { 63 | max-width: 960px; 64 | margin: 100px auto; 65 | } 66 | h1 { 67 | font-weight: 200; 68 | } 69 | footer { 70 | max-width: 960px; 71 | margin: 100px auto 20px auto; 72 | text-align: right; 73 | } 74 | footer p { 75 | margin: 0; 76 | } 77 | .signature { 78 | font-size: 20px; 79 | } 80 | .signature img { 81 | vertical-align: -10px; 82 | margin-right: -40px; 83 | } 84 | .license { 85 | font-size: 12px; 86 | } 87 | 88 | dt { 89 | font-weight: bold; 90 | } 91 | 92 | /* FORMS */ 93 | form { 94 | border: 1px solid #0e9063; 95 | } 96 | .form-line { 97 | padding: 5px 10px; 98 | } 99 | .form-line label { 100 | font-weight: bold; 101 | display: block; 102 | } 103 | .form-line.actions { 104 | text-align: right; 105 | background: #0e9063; 106 | } 107 | 108 | /* we can probably do better, and actually test on a mobile */ 109 | @media (max-width: 1000px) { 110 | main { 111 | margin: 100px 30px; 112 | } 113 | iframe { 114 | width: 100%; 115 | } 116 | } 117 | -------------------------------------------------------------------------------- /design/fonts/fonts.css: -------------------------------------------------------------------------------- 1 | 2 | /* Extra-thin, used for headings */ 3 | @font-face { 4 | font-family: "Titillium"; 5 | src: url("titilliumweb-extralight-webfont.eot"); 6 | src: url("titilliumweb-extralight-webfont.eot?#iefix") format("embedded-opentype"), 7 | url("titilliumweb-extralight-webfont.woff2") format("woff2"), 8 | url("titilliumweb-extralight-webfont.woff") format("woff"), 9 | url("titilliumweb-extralight-webfont.ttf") format("truetype"); 10 | font-weight: 200; 11 | font-style: normal; 12 | } 13 | 14 | /* Light & light italic, used as regular */ 15 | @font-face { 16 | font-family: "Titillium"; 17 | src: url("titilliumweb-light-webfont.eot"); 18 | src: url("titilliumweb-light-webfont.eot?#iefix") format("embedded-opentype"), 19 | url("titilliumweb-light-webfont.woff2") format("woff2"), 20 | url("titilliumweb-light-webfont.woff") format("woff"), 21 | url("titilliumweb-light-webfont.ttf") format("truetype"); 22 | font-weight: normal; 23 | font-style: normal; 24 | } 25 | @font-face { 26 | font-family: "Titillium"; 27 | src: url("titilliumweb-lightitalic-webfont.eot"); 28 | src: url("titilliumweb-lightitalic-webfont.eot?#iefix") format("embedded-opentype"), 29 | url("titilliumweb-lightitalic-webfont.woff2") format("woff2"), 30 | url("titilliumweb-lightitalic-webfont.woff") format("woff"), 31 | url("titilliumweb-lightitalic-webfont.ttf") format("truetype"); 32 | font-weight: normal; 33 | font-style: italic; 34 | } 35 | 36 | /* Semibold & semibold italic, used as bold */ 37 | @font-face { 38 | font-family: "Titillium"; 39 | src: url("titilliumweb-semibold-webfont.eot"); 40 | src: url("titilliumweb-semibold-webfont.eot?#iefix") format("embedded-opentype"), 41 | url("titilliumweb-semibold-webfont.woff2") format("woff2"), 42 | url("titilliumweb-semibold-webfont.woff") format("woff"), 43 | url("titilliumweb-semibold-webfont.ttf") format("truetype"); 44 | font-weight: bold; 45 | font-style: normal; 46 | } 47 | @font-face { 48 | font-family: "Titillium"; 49 | src: url("titilliumweb-semibolditalic-webfont.eot"); 50 | src: url("titilliumweb-semibolditalic-webfont.eot?#iefix") format("embedded-opentype"), 51 | url("titilliumweb-semibolditalic-webfont.woff2") format("woff2"), 52 | url("titilliumweb-semibolditalic-webfont.woff") format("woff"), 53 | url("titilliumweb-semibolditalic-webfont.ttf") format("truetype"); 54 | font-weight: bold; 55 | font-style: italic; 56 | } 57 | -------------------------------------------------------------------------------- /css/fonts.css: -------------------------------------------------------------------------------- 1 | 2 | /* Extra-thin, used for headings */ 3 | @font-face { 4 | font-family: "Titillium"; 5 | src: url("/fonts/titilliumweb-extralight-webfont.eot"); 6 | src: url("/fonts/titilliumweb-extralight-webfont.eot?#iefix") format("embedded-opentype"), 7 | url("/fonts/titilliumweb-extralight-webfont.woff2") format("woff2"), 8 | url("/fonts/titilliumweb-extralight-webfont.woff") format("woff"), 9 | url("/fonts/titilliumweb-extralight-webfont.ttf") format("truetype"); 10 | font-weight: 200; 11 | font-style: normal; 12 | } 13 | 14 | /* Light & light italic, used as regular */ 15 | @font-face { 16 | font-family: "Titillium"; 17 | src: url("/fonts/titilliumweb-light-webfont.eot"); 18 | src: url("/fonts/titilliumweb-light-webfont.eot?#iefix") format("embedded-opentype"), 19 | url("/fonts/titilliumweb-light-webfont.woff2") format("woff2"), 20 | url("/fonts/titilliumweb-light-webfont.woff") format("woff"), 21 | url("/fonts/titilliumweb-light-webfont.ttf") format("truetype"); 22 | font-weight: normal; 23 | font-style: normal; 24 | } 25 | @font-face { 26 | font-family: "Titillium"; 27 | src: url("/fonts/titilliumweb-lightitalic-webfont.eot"); 28 | src: url("/fonts/titilliumweb-lightitalic-webfont.eot?#iefix") format("embedded-opentype"), 29 | url("/fonts/titilliumweb-lightitalic-webfont.woff2") format("woff2"), 30 | url("/fonts/titilliumweb-lightitalic-webfont.woff") format("woff"), 31 | url("/fonts/titilliumweb-lightitalic-webfont.ttf") format("truetype"); 32 | font-weight: normal; 33 | font-style: italic; 34 | } 35 | 36 | /* Semibold & semibold italic, used as bold */ 37 | @font-face { 38 | font-family: "Titillium"; 39 | src: url("/fonts/titilliumweb-semibold-webfont.eot"); 40 | src: url("/fonts/titilliumweb-semibold-webfont.eot?#iefix") format("embedded-opentype"), 41 | url("/fonts/titilliumweb-semibold-webfont.woff2") format("woff2"), 42 | url("/fonts/titilliumweb-semibold-webfont.woff") format("woff"), 43 | url("/fonts/titilliumweb-semibold-webfont.ttf") format("truetype"); 44 | font-weight: bold; 45 | font-style: normal; 46 | } 47 | @font-face { 48 | font-family: "Titillium"; 49 | src: url("/fonts/titilliumweb-semibolditalic-webfont.eot"); 50 | src: url("/fonts/titilliumweb-semibolditalic-webfont.eot?#iefix") format("embedded-opentype"), 51 | url("/fonts/titilliumweb-semibolditalic-webfont.woff2") format("woff2"), 52 | url("/fonts/titilliumweb-semibolditalic-webfont.woff") format("woff"), 53 | url("/fonts/titilliumweb-semibolditalic-webfont.ttf") format("truetype"); 54 | font-weight: bold; 55 | font-style: italic; 56 | } 57 | -------------------------------------------------------------------------------- /tools/tasks/process-html.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | var fs = require("fs-extra"), 4 | jn = require("path").join, 5 | ext = require("path").extname, 6 | whacko = require("whacko"); 7 | 8 | function processHTML(source, target) { 9 | return new Promise(function (resolve, reject) { 10 | fs.readFile(source, "utf8", function (err, data) { 11 | if (err) return reject(err); 12 | var $ = whacko.load(data), 13 | $title = $("title"), 14 | $body = $("body"); 15 | // change head 16 | $("meta[charset]").after(""); 17 | $title.after(""); 18 | $title.after(""); 19 | 20 | // main 21 | var $main = $("
").append($("body").contents()); 22 | $body.append($main); 23 | $main.prepend($("

").text($title.text())); 24 | 25 | // header 26 | $body.prepend("
\n \n

Etiologies

\n \n
"); 27 | 28 | // footer 29 | $body.append(""); 30 | 31 | fs.outputFile(target, $.html(), function (err) { 32 | if (err) return reject(err); 33 | resolve(); 34 | }); 35 | }); 36 | }); 37 | } 38 | 39 | // XXX this is not DRY, we should have it be more generic 40 | module.exports = function (sourceDir, targetDir, tree) { 41 | var proms = []; 42 | for (var k in tree) { 43 | if (!tree[k].isDirectory() && ext(k) === ".html") proms.push(processHTML(jn(sourceDir, k), jn(targetDir, k))); 44 | }return Promise.all(proms); 45 | }; -------------------------------------------------------------------------------- /tools-src/tasks/process-html.js: -------------------------------------------------------------------------------- 1 | 2 | let fs = require("fs-extra") 3 | , jn = require("path").join 4 | , ext = require("path").extname 5 | , whacko = require("whacko") 6 | ; 7 | 8 | function processHTML (source, target) { 9 | return new Promise((resolve, reject) => { 10 | fs.readFile(source, "utf8", (err, data) => { 11 | if (err) return reject(err); 12 | let $ = whacko.load(data) 13 | , $title = $("title") 14 | , $body = $("body") 15 | ; 16 | // change head 17 | $("meta[charset]").after(''); 18 | $title.after(""); 19 | $title.after(""); 20 | 21 | // main 22 | let $main = $("
").append($("body").contents()); 23 | $body.append($main); 24 | $main.prepend($("

").text($title.text())); 25 | 26 | // header 27 | $body.prepend( 28 | `
29 | 30 |

Etiologies

31 | 38 |
` 39 | ); 40 | 41 | // footer 42 | $body.append( 43 | `` 57 | ); 58 | 59 | fs.outputFile(target, $.html(), (err) => { 60 | if (err) return reject(err); 61 | resolve(); 62 | }); 63 | }); 64 | }); 65 | } 66 | 67 | // XXX this is not DRY, we should have it be more generic 68 | module.exports = function (sourceDir, targetDir, tree) { 69 | var proms = []; 70 | for (let k in tree) 71 | if (!tree[k].isDirectory() && ext(k) === ".html") 72 | proms.push(processHTML(jn(sourceDir, k), jn(targetDir, k))); 73 | return Promise.all(proms); 74 | }; 75 | -------------------------------------------------------------------------------- /site/projects/piano-roll/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | One-Dimensional Avalanche Piano Roll 4 | 5 |
6 | 7 |

Etiologies

8 | 15 |

One-Dimensional Avalanche Piano Roll

16 |

17 | This project runs avalanches on one-dimensional, non-looping lattice, with varying 18 | parameters. At every time step (when a grain of sand of dropped on the pile), all the 19 | avalanches that take place mark a bar of their extend on a line beneath the lattice, and the 20 | line is moved down. 21 |

22 |

23 | The idea is to see if it lends itself to some sort of analysis at that level. 24 |

25 |
26 |
27 | 28 | 33 |
34 |
35 | 36 | 37 |
38 |
39 | 40 | 41 |
42 |
43 | 44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 | 52 | 53 | 54 |
-------------------------------------------------------------------------------- /site/about/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | About Etiologies 4 | 5 |
6 | 7 |

Etiologies

8 | 15 |

About Etiologies

16 |

17 | Etiologies is a web site that is maintained as 18 | an open source project to which anyone 19 | can contribute. Its core goal is to «tinker with natural philosophy» using Web technologies. 20 | It is a broad remit, deliberately. 21 |

22 |

23 | The project’s tenets are: 24 |

25 | 45 |

46 | My primary initial focus is on complexity and criticality, but I’m open to contributions on 47 | other topics as well. 48 |

49 |

50 | I claim no expertise. I am simply having fun and tinkering. 51 |

52 | 53 | 54 |
-------------------------------------------------------------------------------- /TODO.txt: -------------------------------------------------------------------------------- 1 | 2 | TODO: 3 | ✓ write about page 4 | - template 5 | ✓ CSS basics 6 | ✓ fonts (moved over) 7 | ✓ header and footer layout 8 | ✓ minimal support for mobile 9 | ✓ scale the iframe down 10 | ✓ position the title and nav differently 11 | ✓ add some margins for main 12 | ✓ favicon 13 | - set up basics of build 14 | ✓ 6to5 15 | ✓ templating 16 | - generating index page 17 | - news sources 18 | ✓ start rsyncing 19 | - write SOC description 20 | - definition indexer 21 | - avalanches experiment 22 | - browserify 23 | - explorable data from offline, larger runs 24 | - open questions 25 | - sticky headers 26 | - random graphs basics 27 | - the different properties of the basic random graphs 28 | - algorithms to build them 29 | - visual explanations of their properties 30 | - avalanches on various topologies 31 | - the Bak brain? 32 | - NK model 33 | - rugged landscapes 34 | - RBNs 35 | - RBNs on various topologies 36 | - the simplest s/b model 37 | - metrics on random graphs (http://arxiv.org/abs/1005.1397? SFI video Antoine Allard) 38 | - dimensions (time-like, space-like) on a graph through information theoretic notions 39 | - reading list 40 | - Calculus of Emergence implementations (ϵ-machines) 41 | 42 | BUILD SYSTEM: 43 | ✓ Babel 44 | ✓ CleanCSS 45 | ✓ browserify 46 | ✓ nodemon 47 | - CSS built to hashed component, cached forever 48 | - JS built to several hashed components, depending on the page 49 | - need to support dependencies 50 | - libs needs to be able to run in the browser but also in Node 51 | - it should be possible to run complex computations in S3 or similar 52 | - definitions and cross-linking 53 | 54 | PROJECTS: 55 | - SOC 56 | - reprise the demo for undefined 57 | - explain it a lot more 58 | - more interactive 59 | - ask questions, then answer then in code 60 | - does topology influence avalanches? 61 | - are there rules governing how long a grain of sand stays on the table? 62 | - Origins of Order notes 63 | - s/b model, a complete implementation 64 | - this might enable a tie-in with social evolution 65 | - WebLogo, port of NetLogo 66 | - see #etiologies in Evernote 67 | 68 | WRITING: 69 | - how http://www.3quarksdaily.com/3quarksdaily/2015/05/how-informative-is-the-concept-of-biological-information.html can 70 | be fixed by applying the epistemology in Calculi of Emergence 71 | - actually write up a full epistemology, based on CoE and other assumptions. It is particularly 72 | important to clarify the centrality of information and computation, with help notably from 73 | The Annotated Turing and probably from Quantum Computing Since Democritus. It may be worth 74 | pointing at issues with Deutsch's epistemology in Four Strands. 75 | 76 | ORGANISATION: 77 | - front page lists latest items and categorised items 78 | - need a section that is basically just "concepts" and the such (e.g. Criticality) 79 | - when any page has an open question, it is extracted and collated in a central list 80 | - definitions can be linked to easily 81 | 82 | INFORMATION: 83 | ✓ about page with goals 84 | - short description of self 85 | - how to contribute 86 | - reading list 87 | - list of read books and papers, with summaries 88 | - DFNs 89 | 90 | INSPIRATION: 91 | ✓ http://www.maartenlambrechts.be/the-rise-of-explorable-explanations/ 92 | - http://worrydream.com/ExplorableExplanations/ 93 | - http://worrydream.com/LadderOfAbstraction/ 94 | - http://setosa.io/ev/ 95 | - http://jackschaedler.github.io/circles-sines-signals/index.html 96 | - http://bost.ocks.org/mike/algorithms/ 97 | - http://ncase.me/polygons/ 98 | - http://blog.ncase.me/explorable-explanations/ 99 | - http://www.redblobgames.com/pathfinding/a-star/introduction.html 100 | - http://www.redblobgames.com/articles/curved-paths/ 101 | - http://pomax.github.io/bezierinfo 102 | - http://www.vizitsolutions.com/portfolio/vfield/ 103 | - https://camdavidsonpilon.github.io/Probabilistic-Programming-and-Bayesian-Methods-for-Hackers 104 | - http://bactra.org/notebooks/complex-networks.html 105 | - http://synaptic.juancazala.com/# 106 | - http://burakkanber.com/blog/learn-to-embrace-dinkiness/ 107 | - http://worrydream.com/MediaForThinkingTheUnthinkable/ 108 | -------------------------------------------------------------------------------- /site/css/etiologies.css: -------------------------------------------------------------------------------- 1 | /*! normalize.css v3.0.3 | MIT License | github.com/necolas/normalize.css */iframe,img,legend{border:0}legend,td,th{padding:0}footer,header,main{max-width:960px}footer,nav ul,p.site-title{text-align:right}html{font-family:sans-serif;-ms-text-size-adjust:100%;-webkit-text-size-adjust:100%}body{margin:0;font-family:Titillium}article,aside,details,figcaption,figure,footer,header,hgroup,main,menu,nav,section,summary{display:block}audio,canvas,progress,video{display:inline-block;vertical-align:baseline}audio:not([controls]){display:none;height:0}[hidden],template{display:none}nav li,nav li a{display:inline-block}a{background-color:transparent}a:active,a:hover{outline:0}abbr[title]{border-bottom:1px dotted}b,optgroup,strong{font-weight:700}dfn{font-style:italic}h1{font-size:2em;margin:.67em 0;font-weight:200}mark{background:#ff0;color:#000}small{font-size:80%}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}sup{top:-.5em}sub{bottom:-.25em}svg:not(:root){overflow:hidden}figure{margin:1em 40px}hr{box-sizing:content-box;height:0}pre,textarea{overflow:auto}code,kbd,pre,samp{font-family:monospace,monospace;font-size:1em}button,input,optgroup,select,textarea{color:inherit;font:inherit;margin:0}button{overflow:visible}button,select{text-transform:none}button,html input[type=button],input[type=reset],input[type=submit]{-webkit-appearance:button;cursor:pointer}button[disabled],html input[disabled]{cursor:default}button::-moz-focus-inner,input::-moz-focus-inner{border:0;padding:0}input{line-height:normal}input[type=checkbox],input[type=radio]{box-sizing:border-box;padding:0}input[type=number]::-webkit-inner-spin-button,input[type=number]::-webkit-outer-spin-button{height:auto}input[type=search]{-webkit-appearance:textfield;box-sizing:content-box}input[type=search]::-webkit-search-cancel-button,input[type=search]::-webkit-search-decoration{-webkit-appearance:none}fieldset{border:1px solid silver;margin:0 2px;padding:.35em .625em .75em}table{border-collapse:collapse;border-spacing:0}@font-face{font-family:Titillium;src:url(/fonts/titilliumweb-extralight-webfont.eot);src:url(/fonts/titilliumweb-extralight-webfont.eot?#iefix)format("embedded-opentype"),url(/fonts/titilliumweb-extralight-webfont.woff2)format("woff2"),url(/fonts/titilliumweb-extralight-webfont.woff)format("woff"),url(/fonts/titilliumweb-extralight-webfont.ttf)format("truetype");font-weight:200;font-style:normal}@font-face{font-family:Titillium;src:url(/fonts/titilliumweb-light-webfont.eot);src:url(/fonts/titilliumweb-light-webfont.eot?#iefix)format("embedded-opentype"),url(/fonts/titilliumweb-light-webfont.woff2)format("woff2"),url(/fonts/titilliumweb-light-webfont.woff)format("woff"),url(/fonts/titilliumweb-light-webfont.ttf)format("truetype");font-weight:400;font-style:normal}@font-face{font-family:Titillium;src:url(/fonts/titilliumweb-lightitalic-webfont.eot);src:url(/fonts/titilliumweb-lightitalic-webfont.eot?#iefix)format("embedded-opentype"),url(/fonts/titilliumweb-lightitalic-webfont.woff2)format("woff2"),url(/fonts/titilliumweb-lightitalic-webfont.woff)format("woff"),url(/fonts/titilliumweb-lightitalic-webfont.ttf)format("truetype");font-weight:400;font-style:italic}@font-face{font-family:Titillium;src:url(/fonts/titilliumweb-semibold-webfont.eot);src:url(/fonts/titilliumweb-semibold-webfont.eot?#iefix)format("embedded-opentype"),url(/fonts/titilliumweb-semibold-webfont.woff2)format("woff2"),url(/fonts/titilliumweb-semibold-webfont.woff)format("woff"),url(/fonts/titilliumweb-semibold-webfont.ttf)format("truetype");font-weight:700;font-style:normal}@font-face{font-family:Titillium;src:url(/fonts/titilliumweb-semibolditalic-webfont.eot);src:url(/fonts/titilliumweb-semibolditalic-webfont.eot?#iefix)format("embedded-opentype"),url(/fonts/titilliumweb-semibolditalic-webfont.woff2)format("woff2"),url(/fonts/titilliumweb-semibolditalic-webfont.woff)format("woff"),url(/fonts/titilliumweb-semibolditalic-webfont.ttf)format("truetype");font-weight:700;font-style:italic}header{margin:auto}p.site-title{margin:-125px 50px 0 0;font-size:50px;font-weight:200}nav ul{list-style-type:none;margin:5px 40px 0 0}nav li a{padding:0 10px;line-height:1;background:0 0}nav li::before{content:"・";color:silver}nav li:first-of-type::before{content:none}a{text-decoration:none;color:#0e9063;background:linear-gradient(transparent 0,transparent 60%,#fff 65%,#fdf3a1 93%,transparent 95%)}a:hover{text-decoration:underline dotted #ff7000}a:active{color:#ff7000}main{margin:100px auto}footer{margin:100px auto 20px}footer p{margin:0}.signature{font-size:20px}.signature img{vertical-align:-10px;margin-right:-40px}.license{font-size:12px}dt{font-weight:700}form{border:1px solid #0e9063}.form-line{padding:5px 10px}.form-line label{font-weight:700;display:block}.form-line.actions{text-align:right;background:#0e9063}@media (max-width:1000px){main{margin:100px 30px}iframe{width:100%}} -------------------------------------------------------------------------------- /design/design.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Etiologi.es 7 | 8 | 92 | 93 | 94 |
95 | 96 |

Etiologies

97 | 105 |
106 |
107 |

Tinkering with Natural Philosophy

108 |

109 | Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt 110 | ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco 111 | laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in 112 | voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat 113 | cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. 114 |

115 |

116 | The Web Platform Tests (WPT) system relies on a code-review engine known as Critic. It 117 | ties into GitHub pull requests and is much more powerful than GitHub’s built-in code 118 | review. 119 |

120 |

121 | Most groups likely do not need Critic, but for more complex code such as that which is 122 | found in tests it is a very welcome improvement. 123 |

124 |

125 | The current Critic instance is run by 126 | James Graham on his personal server, and without HTTPS. While that is not the end of the 127 | world, given how central Critic is to the testing work it would be much better to host 128 | it on W3C. 129 |

130 |

131 | It may be worth investigating the use of Reviewable 132 | as a potential hosted replacement. 133 |

134 |
135 | 149 | 150 | 151 | -------------------------------------------------------------------------------- /site/js/leaves.min.js: -------------------------------------------------------------------------------- 1 | (function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o path:not(.bark)"),barks=document.querySelectorAll("path.bark"),colours=randomColor({hue:"green",count:leaves.length}),barkColours=randomColor({hue:"orange",count:barks.length});for(var i=0,n=leaves.length;icolors.length){colors.push(randomColor(options))}options.count=totalColors;return colors}H=pickHue(options);S=pickSaturation(H,options);B=pickBrightness(H,S,options);return setFormat([H,S,B],options)};function pickHue(options){var hueRange=getHueRange(options.hue),hue=randomWithin(hueRange);if(hue<0){hue=360+hue}return hue}function pickSaturation(hue,options){if(options.luminosity==="random"){return randomWithin([0,100])}if(options.hue==="monochrome"){return 0}var saturationRange=getSaturationRange(hue);var sMin=saturationRange[0],sMax=saturationRange[1];switch(options.luminosity){case"bright":sMin=55;break;case"dark":sMin=sMax-10;break;case"light":sMax=55;break}return randomWithin([sMin,sMax])}function pickBrightness(H,S,options){var brightness,bMin=getMinimumBrightness(H,S),bMax=100;switch(options.luminosity){case"dark":bMax=bMin+20;break;case"light":bMin=(bMax+bMin)/2;break;case"random":bMin=0;bMax=100;break}return randomWithin([bMin,bMax])}function setFormat(hsv,options){switch(options.format){case"hsvArray":return hsv;case"hslArray":return HSVtoHSL(hsv);case"hsl":var hsl=HSVtoHSL(hsv);return"hsl("+hsl[0]+", "+hsl[1]+"%, "+hsl[2]+"%)";case"rgbArray":return HSVtoRGB(hsv);case"rgb":var rgb=HSVtoRGB(hsv);return"rgb("+rgb.join(", ")+")";default:return HSVtoHex(hsv)}}function getMinimumBrightness(H,S){var lowerBounds=getColorInfo(H).lowerBounds;for(var i=0;i=s1&&S<=s2){var m=(v2-v1)/(s2-s1),b=v1-m*s1;return m*S+b}}return 0}function getHueRange(colorInput){if(typeof parseInt(colorInput)==="number"){var number=parseInt(colorInput);if(number<360&&number>0){return[number,number]}}if(typeof colorInput==="string"){if(colorDictionary[colorInput]){var color=colorDictionary[colorInput];if(color.hueRange){return color.hueRange}}}return[0,360]}function getSaturationRange(hue){return getColorInfo(hue).saturationRange}function getColorInfo(hue){if(hue>=334&&hue<=360){hue-=360}for(var colorName in colorDictionary){var color=colorDictionary[colorName];if(color.hueRange&&hue>=color.hueRange[0]&&hue<=color.hueRange[1]){return colorDictionary[colorName]}}return"Color not found"}function randomWithin(range){return Math.floor(range[0]+Math.random()*(range[1]+1-range[0]))}function HSVtoHex(hsv){var rgb=HSVtoRGB(hsv);function componentToHex(c){var hex=c.toString(16);return hex.length==1?"0"+hex:hex}var hex="#"+componentToHex(rgb[0])+componentToHex(rgb[1])+componentToHex(rgb[2]);return hex}function defineColor(name,hueRange,lowerBounds){var sMin=lowerBounds[0][0],sMax=lowerBounds[lowerBounds.length-1][0],bMin=lowerBounds[lowerBounds.length-1][1],bMax=lowerBounds[0][1];colorDictionary[name]={hueRange:hueRange,lowerBounds:lowerBounds,saturationRange:[sMin,sMax],brightnessRange:[bMin,bMax]}}function loadColorBounds(){defineColor("monochrome",null,[[0,0],[100,0]]);defineColor("red",[-26,18],[[20,100],[30,92],[40,89],[50,85],[60,78],[70,70],[80,60],[90,55],[100,50]]);defineColor("orange",[19,46],[[20,100],[30,93],[40,88],[50,86],[60,85],[70,70],[100,70]]);defineColor("yellow",[47,62],[[25,100],[40,94],[50,89],[60,86],[70,84],[80,82],[90,80],[100,75]]);defineColor("green",[63,178],[[30,100],[40,90],[50,85],[60,81],[70,74],[80,64],[90,50],[100,40]]);defineColor("blue",[179,257],[[20,100],[30,86],[40,80],[50,74],[60,60],[70,52],[80,44],[90,39],[100,35]]);defineColor("purple",[258,282],[[20,100],[30,87],[40,79],[50,70],[60,65],[70,59],[80,52],[90,45],[100,42]]);defineColor("pink",[283,334],[[20,100],[30,90],[40,86],[60,84],[80,80],[90,75],[100,73]])}function HSVtoRGB(hsv){var h=hsv[0];if(h===0){h=1}if(h===360){h=359}h=h/360;var s=hsv[1]/100,v=hsv[2]/100;var h_i=Math.floor(h*6),f=h*6-h_i,p=v*(1-s),q=v*(1-f*s),t=v*(1-(1-f)*s),r=256,g=256,b=256;switch(h_i){case 0:r=v,g=t,b=p;break;case 1:r=q,g=v,b=p;break;case 2:r=p,g=v,b=t;break;case 3:r=p,g=q,b=v;break;case 4:r=t,g=p,b=v;break;case 5:r=v,g=p,b=q;break}var result=[Math.floor(r*255),Math.floor(g*255),Math.floor(b*255)];return result}function HSVtoHSL(hsv){var h=hsv[0],s=hsv[1]/100,v=hsv[2]/100,k=(2-s)*v;return[h,Math.round(s*v/(k<1?k:2-k)*1e4)/100,k/2*100]}return randomColor})},{}]},{},[1]); -------------------------------------------------------------------------------- /design/randomColor.js: -------------------------------------------------------------------------------- 1 | ;(function(root, factory) { 2 | 3 | // Support AMD 4 | if (typeof define === 'function' && define.amd) { 5 | define([], factory); 6 | 7 | // Support CommonJS 8 | } else if (typeof exports === 'object') { 9 | var randomColor = factory(); 10 | 11 | // Support NodeJS & Component, which allow module.exports to be a function 12 | if (typeof module === 'object' && module && module.exports) { 13 | exports = module.exports = randomColor; 14 | } 15 | 16 | // Support CommonJS 1.1.1 spec 17 | exports.randomColor = randomColor; 18 | 19 | // Support vanilla script loading 20 | } else { 21 | root.randomColor = factory(); 22 | }; 23 | 24 | }(this, function() { 25 | 26 | // Shared color dictionary 27 | var colorDictionary = {}; 28 | 29 | // Populate the color dictionary 30 | loadColorBounds(); 31 | 32 | var randomColor = function(options) { 33 | options = options || {}; 34 | 35 | var H,S,B; 36 | 37 | // Check if we need to generate multiple colors 38 | if (options.count != null) { 39 | 40 | var totalColors = options.count, 41 | colors = []; 42 | 43 | options.count = null; 44 | 45 | while (totalColors > colors.length) { 46 | colors.push(randomColor(options)); 47 | } 48 | 49 | options.count = totalColors; 50 | 51 | return colors; 52 | } 53 | 54 | // First we pick a hue (H) 55 | H = pickHue(options); 56 | 57 | // Then use H to determine saturation (S) 58 | S = pickSaturation(H, options); 59 | 60 | // Then use S and H to determine brightness (B). 61 | B = pickBrightness(H, S, options); 62 | 63 | // Then we return the HSB color in the desired format 64 | return setFormat([H,S,B], options); 65 | }; 66 | 67 | function pickHue (options) { 68 | 69 | var hueRange = getHueRange(options.hue), 70 | hue = randomWithin(hueRange); 71 | 72 | // Instead of storing red as two seperate ranges, 73 | // we group them, using negative numbers 74 | if (hue < 0) {hue = 360 + hue} 75 | 76 | return hue; 77 | 78 | } 79 | 80 | function pickSaturation (hue, options) { 81 | 82 | if (options.luminosity === 'random') { 83 | return randomWithin([0,100]); 84 | } 85 | 86 | if (options.hue === 'monochrome') { 87 | return 0; 88 | } 89 | 90 | var saturationRange = getSaturationRange(hue); 91 | 92 | var sMin = saturationRange[0], 93 | sMax = saturationRange[1]; 94 | 95 | switch (options.luminosity) { 96 | 97 | case 'bright': 98 | sMin = 55; 99 | break; 100 | 101 | case 'dark': 102 | sMin = sMax - 10; 103 | break; 104 | 105 | case 'light': 106 | sMax = 55; 107 | break; 108 | } 109 | 110 | return randomWithin([sMin, sMax]); 111 | 112 | } 113 | 114 | function pickBrightness (H, S, options) { 115 | 116 | var brightness, 117 | bMin = getMinimumBrightness(H, S), 118 | bMax = 100; 119 | 120 | switch (options.luminosity) { 121 | 122 | case 'dark': 123 | bMax = bMin + 20; 124 | break; 125 | 126 | case 'light': 127 | bMin = (bMax + bMin)/2; 128 | break; 129 | 130 | case 'random': 131 | bMin = 0; 132 | bMax = 100; 133 | break; 134 | } 135 | 136 | return randomWithin([bMin, bMax]); 137 | 138 | } 139 | 140 | function setFormat (hsv, options) { 141 | 142 | switch (options.format) { 143 | 144 | case 'hsvArray': 145 | return hsv; 146 | 147 | case 'hslArray': 148 | return HSVtoHSL(hsv); 149 | 150 | case 'hsl': 151 | var hsl = HSVtoHSL(hsv); 152 | return 'hsl('+hsl[0]+', '+hsl[1]+'%, '+hsl[2]+'%)'; 153 | 154 | case 'rgbArray': 155 | return HSVtoRGB(hsv); 156 | 157 | case 'rgb': 158 | var rgb = HSVtoRGB(hsv); 159 | return 'rgb(' + rgb.join(', ') + ')'; 160 | 161 | default: 162 | return HSVtoHex(hsv); 163 | } 164 | 165 | } 166 | 167 | function getMinimumBrightness(H, S) { 168 | 169 | var lowerBounds = getColorInfo(H).lowerBounds; 170 | 171 | for (var i = 0; i < lowerBounds.length - 1; i++) { 172 | 173 | var s1 = lowerBounds[i][0], 174 | v1 = lowerBounds[i][1]; 175 | 176 | var s2 = lowerBounds[i+1][0], 177 | v2 = lowerBounds[i+1][1]; 178 | 179 | if (S >= s1 && S <= s2) { 180 | 181 | var m = (v2 - v1)/(s2 - s1), 182 | b = v1 - m*s1; 183 | 184 | return m*S + b; 185 | } 186 | 187 | } 188 | 189 | return 0; 190 | } 191 | 192 | function getHueRange (colorInput) { 193 | 194 | if (typeof parseInt(colorInput) === 'number') { 195 | 196 | var number = parseInt(colorInput); 197 | 198 | if (number < 360 && number > 0) { 199 | return [number, number]; 200 | } 201 | 202 | } 203 | 204 | if (typeof colorInput === 'string') { 205 | 206 | if (colorDictionary[colorInput]) { 207 | var color = colorDictionary[colorInput]; 208 | if (color.hueRange) {return color.hueRange} 209 | } 210 | } 211 | 212 | return [0,360]; 213 | 214 | } 215 | 216 | function getSaturationRange (hue) { 217 | return getColorInfo(hue).saturationRange; 218 | } 219 | 220 | function getColorInfo (hue) { 221 | 222 | // Maps red colors to make picking hue easier 223 | if (hue >= 334 && hue <= 360) { 224 | hue-= 360; 225 | } 226 | 227 | for (var colorName in colorDictionary) { 228 | var color = colorDictionary[colorName]; 229 | if (color.hueRange && 230 | hue >= color.hueRange[0] && 231 | hue <= color.hueRange[1]) { 232 | return colorDictionary[colorName]; 233 | } 234 | } return 'Color not found'; 235 | } 236 | 237 | function randomWithin (range) { 238 | return Math.floor(range[0] + Math.random()*(range[1] + 1 - range[0])); 239 | } 240 | 241 | function HSVtoHex (hsv){ 242 | 243 | var rgb = HSVtoRGB(hsv); 244 | 245 | function componentToHex(c) { 246 | var hex = c.toString(16); 247 | return hex.length == 1 ? "0" + hex : hex; 248 | } 249 | 250 | var hex = "#" + componentToHex(rgb[0]) + componentToHex(rgb[1]) + componentToHex(rgb[2]); 251 | 252 | return hex; 253 | 254 | } 255 | 256 | function defineColor (name, hueRange, lowerBounds) { 257 | 258 | var sMin = lowerBounds[0][0], 259 | sMax = lowerBounds[lowerBounds.length - 1][0], 260 | 261 | bMin = lowerBounds[lowerBounds.length - 1][1], 262 | bMax = lowerBounds[0][1]; 263 | 264 | colorDictionary[name] = { 265 | hueRange: hueRange, 266 | lowerBounds: lowerBounds, 267 | saturationRange: [sMin, sMax], 268 | brightnessRange: [bMin, bMax] 269 | }; 270 | 271 | } 272 | 273 | function loadColorBounds () { 274 | 275 | defineColor( 276 | 'monochrome', 277 | null, 278 | [[0,0],[100,0]] 279 | ); 280 | 281 | defineColor( 282 | 'red', 283 | [-26,18], 284 | [[20,100],[30,92],[40,89],[50,85],[60,78],[70,70],[80,60],[90,55],[100,50]] 285 | ); 286 | 287 | defineColor( 288 | 'orange', 289 | [19,46], 290 | [[20,100],[30,93],[40,88],[50,86],[60,85],[70,70],[100,70]] 291 | ); 292 | 293 | defineColor( 294 | 'yellow', 295 | [47,62], 296 | [[25,100],[40,94],[50,89],[60,86],[70,84],[80,82],[90,80],[100,75]] 297 | ); 298 | 299 | defineColor( 300 | 'green', 301 | [63,178], 302 | [[30,100],[40,90],[50,85],[60,81],[70,74],[80,64],[90,50],[100,40]] 303 | ); 304 | 305 | defineColor( 306 | 'blue', 307 | [179, 257], 308 | [[20,100],[30,86],[40,80],[50,74],[60,60],[70,52],[80,44],[90,39],[100,35]] 309 | ); 310 | 311 | defineColor( 312 | 'purple', 313 | [258, 282], 314 | [[20,100],[30,87],[40,79],[50,70],[60,65],[70,59],[80,52],[90,45],[100,42]] 315 | ); 316 | 317 | defineColor( 318 | 'pink', 319 | [283, 334], 320 | [[20,100],[30,90],[40,86],[60,84],[80,80],[90,75],[100,73]] 321 | ); 322 | 323 | } 324 | 325 | function HSVtoRGB (hsv) { 326 | 327 | // this doesn't work for the values of 0 and 360 328 | // here's the hacky fix 329 | var h = hsv[0]; 330 | if (h === 0) {h = 1} 331 | if (h === 360) {h = 359} 332 | 333 | // Rebase the h,s,v values 334 | h = h/360; 335 | var s = hsv[1]/100, 336 | v = hsv[2]/100; 337 | 338 | var h_i = Math.floor(h*6), 339 | f = h * 6 - h_i, 340 | p = v * (1 - s), 341 | q = v * (1 - f*s), 342 | t = v * (1 - (1 - f)*s), 343 | r = 256, 344 | g = 256, 345 | b = 256; 346 | 347 | switch(h_i) { 348 | case 0: r = v, g = t, b = p; break; 349 | case 1: r = q, g = v, b = p; break; 350 | case 2: r = p, g = v, b = t; break; 351 | case 3: r = p, g = q, b = v; break; 352 | case 4: r = t, g = p, b = v; break; 353 | case 5: r = v, g = p, b = q; break; 354 | } 355 | var result = [Math.floor(r*255), Math.floor(g*255), Math.floor(b*255)]; 356 | return result; 357 | } 358 | 359 | function HSVtoHSL (hsv) { 360 | var h = hsv[0], 361 | s = hsv[1]/100, 362 | v = hsv[2]/100, 363 | k = (2-s)*v; 364 | 365 | return [ 366 | h, 367 | Math.round(s*v / (k<1 ? k : 2-k) * 10000) / 100, 368 | k/2 * 100 369 | ]; 370 | } 371 | 372 | return randomColor; 373 | })); 374 | -------------------------------------------------------------------------------- /site/js/leaves.js: -------------------------------------------------------------------------------- 1 | (function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o path:not(.bark)"), 6 | barks = document.querySelectorAll("path.bark") 7 | // hue: red, orange, yellow, green, blue, purple, pink, monochrome 8 | // luminosity: light 9 | , 10 | colours = randomColor({ hue: "green", count: leaves.length }), 11 | barkColours = randomColor({ hue: "orange", count: barks.length }); 12 | for (var i = 0, n = leaves.length; i < n; i++) { 13 | leaves[i].setAttributeNS(null, "fill", colours[i]); 14 | }for (var i = 0, n = barks.length; i < n; i++) { 15 | barks[i].setAttributeNS(null, "fill", barkColours[i]); 16 | } 17 | 18 | },{"randomcolor":2}],2:[function(require,module,exports){ 19 | ;(function(root, factory) { 20 | 21 | // Support AMD 22 | if (typeof define === 'function' && define.amd) { 23 | define([], factory); 24 | 25 | // Support CommonJS 26 | } else if (typeof exports === 'object') { 27 | var randomColor = factory(); 28 | 29 | // Support NodeJS & Component, which allow module.exports to be a function 30 | if (typeof module === 'object' && module && module.exports) { 31 | exports = module.exports = randomColor; 32 | } 33 | 34 | // Support CommonJS 1.1.1 spec 35 | exports.randomColor = randomColor; 36 | 37 | // Support vanilla script loading 38 | } else { 39 | root.randomColor = factory(); 40 | }; 41 | 42 | }(this, function() { 43 | 44 | // Shared color dictionary 45 | var colorDictionary = {}; 46 | 47 | // Populate the color dictionary 48 | loadColorBounds(); 49 | 50 | var randomColor = function(options) { 51 | options = options || {}; 52 | 53 | var H,S,B; 54 | 55 | // Check if we need to generate multiple colors 56 | if (options.count != null) { 57 | 58 | var totalColors = options.count, 59 | colors = []; 60 | 61 | options.count = null; 62 | 63 | while (totalColors > colors.length) { 64 | colors.push(randomColor(options)); 65 | } 66 | 67 | options.count = totalColors; 68 | 69 | return colors; 70 | } 71 | 72 | // First we pick a hue (H) 73 | H = pickHue(options); 74 | 75 | // Then use H to determine saturation (S) 76 | S = pickSaturation(H, options); 77 | 78 | // Then use S and H to determine brightness (B). 79 | B = pickBrightness(H, S, options); 80 | 81 | // Then we return the HSB color in the desired format 82 | return setFormat([H,S,B], options); 83 | }; 84 | 85 | function pickHue (options) { 86 | 87 | var hueRange = getHueRange(options.hue), 88 | hue = randomWithin(hueRange); 89 | 90 | // Instead of storing red as two seperate ranges, 91 | // we group them, using negative numbers 92 | if (hue < 0) {hue = 360 + hue} 93 | 94 | return hue; 95 | 96 | } 97 | 98 | function pickSaturation (hue, options) { 99 | 100 | if (options.luminosity === 'random') { 101 | return randomWithin([0,100]); 102 | } 103 | 104 | if (options.hue === 'monochrome') { 105 | return 0; 106 | } 107 | 108 | var saturationRange = getSaturationRange(hue); 109 | 110 | var sMin = saturationRange[0], 111 | sMax = saturationRange[1]; 112 | 113 | switch (options.luminosity) { 114 | 115 | case 'bright': 116 | sMin = 55; 117 | break; 118 | 119 | case 'dark': 120 | sMin = sMax - 10; 121 | break; 122 | 123 | case 'light': 124 | sMax = 55; 125 | break; 126 | } 127 | 128 | return randomWithin([sMin, sMax]); 129 | 130 | } 131 | 132 | function pickBrightness (H, S, options) { 133 | 134 | var brightness, 135 | bMin = getMinimumBrightness(H, S), 136 | bMax = 100; 137 | 138 | switch (options.luminosity) { 139 | 140 | case 'dark': 141 | bMax = bMin + 20; 142 | break; 143 | 144 | case 'light': 145 | bMin = (bMax + bMin)/2; 146 | break; 147 | 148 | case 'random': 149 | bMin = 0; 150 | bMax = 100; 151 | break; 152 | } 153 | 154 | return randomWithin([bMin, bMax]); 155 | 156 | } 157 | 158 | function setFormat (hsv, options) { 159 | 160 | switch (options.format) { 161 | 162 | case 'hsvArray': 163 | return hsv; 164 | 165 | case 'hslArray': 166 | return HSVtoHSL(hsv); 167 | 168 | case 'hsl': 169 | var hsl = HSVtoHSL(hsv); 170 | return 'hsl('+hsl[0]+', '+hsl[1]+'%, '+hsl[2]+'%)'; 171 | 172 | case 'rgbArray': 173 | return HSVtoRGB(hsv); 174 | 175 | case 'rgb': 176 | var rgb = HSVtoRGB(hsv); 177 | return 'rgb(' + rgb.join(', ') + ')'; 178 | 179 | default: 180 | return HSVtoHex(hsv); 181 | } 182 | 183 | } 184 | 185 | function getMinimumBrightness(H, S) { 186 | 187 | var lowerBounds = getColorInfo(H).lowerBounds; 188 | 189 | for (var i = 0; i < lowerBounds.length - 1; i++) { 190 | 191 | var s1 = lowerBounds[i][0], 192 | v1 = lowerBounds[i][1]; 193 | 194 | var s2 = lowerBounds[i+1][0], 195 | v2 = lowerBounds[i+1][1]; 196 | 197 | if (S >= s1 && S <= s2) { 198 | 199 | var m = (v2 - v1)/(s2 - s1), 200 | b = v1 - m*s1; 201 | 202 | return m*S + b; 203 | } 204 | 205 | } 206 | 207 | return 0; 208 | } 209 | 210 | function getHueRange (colorInput) { 211 | 212 | if (typeof parseInt(colorInput) === 'number') { 213 | 214 | var number = parseInt(colorInput); 215 | 216 | if (number < 360 && number > 0) { 217 | return [number, number]; 218 | } 219 | 220 | } 221 | 222 | if (typeof colorInput === 'string') { 223 | 224 | if (colorDictionary[colorInput]) { 225 | var color = colorDictionary[colorInput]; 226 | if (color.hueRange) {return color.hueRange} 227 | } 228 | } 229 | 230 | return [0,360]; 231 | 232 | } 233 | 234 | function getSaturationRange (hue) { 235 | return getColorInfo(hue).saturationRange; 236 | } 237 | 238 | function getColorInfo (hue) { 239 | 240 | // Maps red colors to make picking hue easier 241 | if (hue >= 334 && hue <= 360) { 242 | hue-= 360; 243 | } 244 | 245 | for (var colorName in colorDictionary) { 246 | var color = colorDictionary[colorName]; 247 | if (color.hueRange && 248 | hue >= color.hueRange[0] && 249 | hue <= color.hueRange[1]) { 250 | return colorDictionary[colorName]; 251 | } 252 | } return 'Color not found'; 253 | } 254 | 255 | function randomWithin (range) { 256 | return Math.floor(range[0] + Math.random()*(range[1] + 1 - range[0])); 257 | } 258 | 259 | function HSVtoHex (hsv){ 260 | 261 | var rgb = HSVtoRGB(hsv); 262 | 263 | function componentToHex(c) { 264 | var hex = c.toString(16); 265 | return hex.length == 1 ? "0" + hex : hex; 266 | } 267 | 268 | var hex = "#" + componentToHex(rgb[0]) + componentToHex(rgb[1]) + componentToHex(rgb[2]); 269 | 270 | return hex; 271 | 272 | } 273 | 274 | function defineColor (name, hueRange, lowerBounds) { 275 | 276 | var sMin = lowerBounds[0][0], 277 | sMax = lowerBounds[lowerBounds.length - 1][0], 278 | 279 | bMin = lowerBounds[lowerBounds.length - 1][1], 280 | bMax = lowerBounds[0][1]; 281 | 282 | colorDictionary[name] = { 283 | hueRange: hueRange, 284 | lowerBounds: lowerBounds, 285 | saturationRange: [sMin, sMax], 286 | brightnessRange: [bMin, bMax] 287 | }; 288 | 289 | } 290 | 291 | function loadColorBounds () { 292 | 293 | defineColor( 294 | 'monochrome', 295 | null, 296 | [[0,0],[100,0]] 297 | ); 298 | 299 | defineColor( 300 | 'red', 301 | [-26,18], 302 | [[20,100],[30,92],[40,89],[50,85],[60,78],[70,70],[80,60],[90,55],[100,50]] 303 | ); 304 | 305 | defineColor( 306 | 'orange', 307 | [19,46], 308 | [[20,100],[30,93],[40,88],[50,86],[60,85],[70,70],[100,70]] 309 | ); 310 | 311 | defineColor( 312 | 'yellow', 313 | [47,62], 314 | [[25,100],[40,94],[50,89],[60,86],[70,84],[80,82],[90,80],[100,75]] 315 | ); 316 | 317 | defineColor( 318 | 'green', 319 | [63,178], 320 | [[30,100],[40,90],[50,85],[60,81],[70,74],[80,64],[90,50],[100,40]] 321 | ); 322 | 323 | defineColor( 324 | 'blue', 325 | [179, 257], 326 | [[20,100],[30,86],[40,80],[50,74],[60,60],[70,52],[80,44],[90,39],[100,35]] 327 | ); 328 | 329 | defineColor( 330 | 'purple', 331 | [258, 282], 332 | [[20,100],[30,87],[40,79],[50,70],[60,65],[70,59],[80,52],[90,45],[100,42]] 333 | ); 334 | 335 | defineColor( 336 | 'pink', 337 | [283, 334], 338 | [[20,100],[30,90],[40,86],[60,84],[80,80],[90,75],[100,73]] 339 | ); 340 | 341 | } 342 | 343 | function HSVtoRGB (hsv) { 344 | 345 | // this doesn't work for the values of 0 and 360 346 | // here's the hacky fix 347 | var h = hsv[0]; 348 | if (h === 0) {h = 1} 349 | if (h === 360) {h = 359} 350 | 351 | // Rebase the h,s,v values 352 | h = h/360; 353 | var s = hsv[1]/100, 354 | v = hsv[2]/100; 355 | 356 | var h_i = Math.floor(h*6), 357 | f = h * 6 - h_i, 358 | p = v * (1 - s), 359 | q = v * (1 - f*s), 360 | t = v * (1 - (1 - f)*s), 361 | r = 256, 362 | g = 256, 363 | b = 256; 364 | 365 | switch(h_i) { 366 | case 0: r = v, g = t, b = p; break; 367 | case 1: r = q, g = v, b = p; break; 368 | case 2: r = p, g = v, b = t; break; 369 | case 3: r = p, g = q, b = v; break; 370 | case 4: r = t, g = p, b = v; break; 371 | case 5: r = v, g = p, b = q; break; 372 | } 373 | var result = [Math.floor(r*255), Math.floor(g*255), Math.floor(b*255)]; 374 | return result; 375 | } 376 | 377 | function HSVtoHSL (hsv) { 378 | var h = hsv[0], 379 | s = hsv[1]/100, 380 | v = hsv[2]/100, 381 | k = (2-s)*v; 382 | 383 | return [ 384 | h, 385 | Math.round(s*v / (k<1 ? k : 2-k) * 10000) / 100, 386 | k/2 * 100 387 | ]; 388 | } 389 | 390 | return randomColor; 391 | })); 392 | 393 | },{}]},{},[1]); 394 | -------------------------------------------------------------------------------- /tools/build-site.js: -------------------------------------------------------------------------------- 1 | 2 | // load up Babel 3 | "use strict"; 4 | 5 | require("babel/polyfill"); 6 | 7 | var jn = require("path").join, 8 | rel = require("./utils/rel")(jn(__dirname, "..")), 9 | contentDir = rel("content"), 10 | siteDir = rel("site"), 11 | sourceTree = require("./tasks/source-tree"), 12 | copyTree = require("./tasks/copy-tree"), 13 | copyStatic = require("./tasks/copy-static"), 14 | processHTML = require("./tasks/process-html"), 15 | buildProject = require("./tasks/build-project"), 16 | tree = undefined; 17 | 18 | sourceTree(contentDir).then(function (t) { 19 | tree = t; 20 | }).then(function () { 21 | return copyTree(siteDir, tree); 22 | }).then(function () { 23 | return copyStatic(contentDir, siteDir, tree); 24 | }).then(function () { 25 | return processHTML(contentDir, siteDir, tree); 26 | }).then(function () { 27 | return buildProject(contentDir, siteDir, tree); 28 | }).then(function () { 29 | console.log("Ok!"); 30 | })["catch"](function (err) { 31 | console.error("BOOM", err); 32 | }); 33 | 34 | // build output directory tree 35 | // copy all non-HTML 36 | // process all HTML 37 | // - templates 38 | 39 | // var fs = require("fs-extra") 40 | // , pth = require("path") 41 | // , crypto = require("crypto") 42 | // , findit = require("findit") 43 | // , async = require("async") 44 | // , whacko = require("whacko") 45 | // , CleanCSS = require("clean-css") 46 | // // , nopt = require("nopt") 47 | // // , knownOpts = { 48 | // // "force": Boolean 49 | // // } 50 | // // , shortHands = { 51 | // // "f" : ["--force"] 52 | // // } 53 | // // , parsedOpt = nopt(knownOpts, shortHands) 54 | // , rel = function (to) { return pth.join(__dirname, to); } 55 | // , rfs = function (file) { return fs.readFileSync(file, "utf8"); } 56 | // , wfs = function (file, content) { fs.writeFileSync(file, content, { encoding: "utf8" }); } 57 | // , norm = function (str) { return str.replace(/\s+/g, " ").replace(/(^\s+|\s+$)/g, ""); } 58 | // , escAttr = function (str) { return str.replace(/&/g, "&").replace(/"/g, """); } 59 | // , escXML = function (str) { return str.replace(/&/g, "&").replace(/ Copying .............. " + output.replace(publishDir, "")); 90 | // fs.copySync(input, output); 91 | // } 92 | // 93 | // // process HTML source file 94 | // function processHTML (input, output) { 95 | // console.log("> Processing ........... " + output.replace(publishDir, "")); 96 | // var $ = whacko.load(rfs(input)) 97 | // , $tmpl = whacko.load(rfs(pth.join(tmplDir, "page.html"))) 98 | // , $html = $tmpl("html") 99 | // ; 100 | // // if ($("html").attr("skip")) return copyFile(input, output); 101 | // if ($("html").attr("skip")) return wfs(output, rfs(input).replace(/\s+skip=['"]?true['"]?/, "")); 102 | // var doc = { 103 | // lang: $("html").attr("lang") || "en" 104 | // , title: $("h1").html() 105 | // , subtitle: $("h2").html() 106 | // , date: $("html").attr("date") 107 | // , blurb: $("div.blurb").length ? $("div.blurb").html() : "

" + $("section > p").first().html() + "

" 108 | // , link: output.replace(publishDir, "").replace("index.html", "") 109 | // } 110 | // ; 111 | // doc.blurbText = $("div.blurb").text() || $("section > p").first().text(); 112 | // doc.url = "http://berjon.com" + doc.link; 113 | // 114 | // // head stuff 115 | // $html.attr("lang", doc.lang); 116 | // $html.find("title").text($("h1").text() + " | Robin Berjon"); 117 | // $html.find("link[rel=stylesheet]").attr("href", cssPath); 118 | // 119 | // // Twitter &FB cards 120 | // var title = $("h1").text() + " — " + $("h2").text(); 121 | // $html.find("meta[property='twitter:title']").attr("content", title); 122 | // $html.find("meta[property='og:title']").attr("content", title); 123 | // var desc = norm(escAttr(doc.blurbText)); 124 | // $html.find("meta[property='twitter:description']").attr("content", desc); 125 | // $html.find("meta[property='og:description']").attr("content", desc); 126 | // // XXX make this possibly use an image from the content or an attribute 127 | // if (!randomCards[doc.link]) 128 | // randomCards[doc.link] = "http://berjon.com/img/card-pics/" + cardImgs[Math.floor(Math.random() * cardImgs.length)] + ".jpg"; 129 | // $html.find("meta[property='twitter:image']").attr("content", randomCards[doc.link]); 130 | // $html.find("meta[property='og:image']").attr("content", randomCards[doc.link]); 131 | // $html.find("meta[property='twitter:url']").attr("content", doc.url); 132 | // $html.find("meta[property='og:url']").attr("content", doc.url); 133 | // $html.find("meta[property='og:locale']").attr("content", fbLocales[doc.lang]); 134 | // 135 | // // body 136 | // $html.find("h1").append($("h1").contents()); 137 | // $html.find("h2").append($("h2").contents()); 138 | // var tags = ($("html").attr("tags") || "No category") 139 | // .split(/\s*,\s*/) 140 | // .map(function (str) { 141 | // return str.charAt(0).toUpperCase() + str.slice(1); 142 | // }) 143 | // .join(", ") 144 | // , doList = tags !== "No category" 145 | // ; 146 | // $html.find("div.meta") 147 | // // .text(tags + " | ") 148 | // .append($("").text(doc.date)) 149 | // ; 150 | // // doc.tags = tags; 151 | // $html.find("article").append($("section")); 152 | // $html.find("q") 153 | // .each(function () { 154 | // var $span = $("").append($(this).contents()); 155 | // $(this) 156 | // .before("“") 157 | // .after("”") 158 | // .replaceWith($span) 159 | // ; 160 | // }) 161 | // ; 162 | // $html.find("p").last().append($("")); 163 | // var asides = 0 164 | // , $art = $html.find("article") 165 | // ; 166 | // $html.find("span.fn") 167 | // .each(function () { 168 | // asides++; 169 | // $(this).replaceWith($("" + asides + "")); 170 | // var $div = $("
" + asides + ".
"); 171 | // $div.append($(this).contents()); 172 | // $art.append($div); 173 | // }); 174 | // 175 | // if ($("html").attr("noindex")) doList = false; 176 | // if (doList) allDocs.push(doc); 177 | // wfs(output, $tmpl.html().replace(/&apos;/g, "'")); 178 | // } 179 | // 180 | // // process CSS source file 181 | // function processCSS (input, output) { 182 | // console.log("> CSS .................. " + output.replace(publishDir, "")); 183 | // var css = rfs(input) 184 | // , cssmin = new CleanCSS({ 185 | // keepSpecialComments: 0 186 | // , root: __dirname 187 | // , relativeTo: styleDir 188 | // , processImport: true 189 | // , noAdvanced: true 190 | // }) 191 | // , minned = cssmin.minify(css) 192 | // , hash = crypto.createHash("md5").update(minned).digest("hex") 193 | // ; 194 | // output = pth.join(pth.dirname(output), hash + ".css"); 195 | // cssPath = "/css/" + hash + ".css"; 196 | // wfs(output, minned); 197 | // } 198 | // 199 | // // finder callback to copy directory tree 200 | // function copyTreeCB (trimDir) { 201 | // return function (dir, stat) { 202 | // if (stat.ctime.getTime() <= lastRun) return; 203 | // var toPub = pubPath(dir, trimDir); 204 | // console.log("> Creating directory ... " + (toPub.replace(publishDir, "") || "/")); 205 | // fs.mkdirpSync(toPub); 206 | // }; 207 | // } 208 | // 209 | // // find everything that has been modified since last time 210 | // function buildContent (cb) { 211 | // var finder = findit(contentDir); 212 | // finder.on("directory", copyTreeCB()); 213 | // finder.on("file", function (file, stat) { 214 | // if (stat.ctime.getTime() <= lastRun) return; 215 | // if (pth.extname(file) === ".html") processHTML(file, pubPath(file)); 216 | // else copyFile(file, pubPath(file)); 217 | // }); 218 | // finder.on("end", cb); 219 | // } 220 | // 221 | // // produce an index body from a list of docs 222 | // function listDocs (docs) { 223 | // var $item = whacko.load(rfs(pth.join(tmplDir, "index-item.html"))) 224 | // , list = "" 225 | // ; 226 | // 227 | // docs.forEach(function (doc) { 228 | // var $art = $item("article").clone() 229 | // , $a = $item("") 230 | // ; 231 | // $art.attr("lang", doc.lang); 232 | // $a.attr("href", doc.link).html(doc.title); 233 | // $art.find("h1").append($a); 234 | // $art.find("h2").html(doc.subtitle); 235 | // $art.find("div.meta") 236 | // // .text(doc.tags + " | ") 237 | // .append($item("").text(doc.date)) 238 | // ; 239 | // $art.append(doc.blurb); 240 | // $art.find("p img").each(function () { 241 | // var $img = $item(this) 242 | // , src = $img.attr("src") 243 | // ; 244 | // if (/^https?:/i.test(src)) return; 245 | // if (/\.\./.test(src)) return; 246 | // if (/^\//.test(src)) return; 247 | // $img.attr("src", doc.link + src); 248 | // }); 249 | // list += "
\n" + $art.html() + "\n
\n"; 250 | // }); 251 | // return list; 252 | // } 253 | // 254 | // // produce an index document 255 | // function makeIndex (data) { 256 | // var $tmpl = whacko.load(rfs(pth.join(tmplDir, "index.html"))) 257 | // , $html = $tmpl("html") 258 | // ; 259 | // $html.attr("lang", data.lang); 260 | // $html.find("title").text(data.title); 261 | // $html.find("link[rel=stylesheet]").attr("href", cssPath); 262 | // $html.find("main").html(data.body); 263 | // $html.find("main").after($tmpl(data.years)); 264 | // return $tmpl.html(); 265 | // } 266 | // 267 | // 268 | // // build the index stuff 269 | // function buildIndex (cb) { 270 | // allDocs.sort(function (a, b) { 271 | // if (a.date < b.date) return 1; 272 | // if (a.date > b.date) return -1; 273 | // return 0; 274 | // }); 275 | // 276 | // // list every year, and for each produce its index 277 | // var years = {}; 278 | // allDocs.forEach(function (doc) { 279 | // var year = doc.date.replace(/^(\d{4}).*/, "$1"); 280 | // if (!years[year]) years[year] = []; 281 | // years[year].push(doc); 282 | // }); 283 | // var allYears = "
    " + 284 | // Object.keys(years) 285 | // .sort() 286 | // .map(function (year) { 287 | // return "
  • " + year + "
  • "; 288 | // }) 289 | // .join("\n") + 290 | // "
" 291 | // ; 292 | // for (var year in years) { 293 | // console.log("> Generating index for year " + year); 294 | // fs.mkdirpSync(pth.join(publishDir, year)); 295 | // wfs(pth.join(publishDir, year, "index.html"), makeIndex({ 296 | // title: "Robin Berjon articles in " + year 297 | // , lang: "en" 298 | // , body: listDocs(years[year]) 299 | // , years: allYears 300 | // })); 301 | // } 302 | // 303 | // // most recent 30 on root index 304 | // console.log("> Generating front index"); 305 | // var root = { 306 | // title: "Robin Berjon" 307 | // , lang: "en" 308 | // , body: listDocs(allDocs.slice(0, 30)) 309 | // , years: allYears 310 | // } 311 | // ; 312 | // wfs(pth.join(publishDir, "index.html"), makeIndex(root)); 313 | // 314 | // // Atom 315 | // var atomTmpl = rfs(pth.join(tmplDir, "feed.atom")) 316 | // , entryTmpl = rfs(pth.join(tmplDir, "entry.atom")) 317 | // , entries = allDocs 318 | // .slice(0, 30) 319 | // .map(function (doc) { 320 | // return entryTmpl.replace(/\{\{(\w+)\}\}/g, function (m, key) { 321 | // return escXML(doc[key]) || "XXX"; 322 | // }); 323 | // }) 324 | // .join("\n") 325 | // , atom = atomTmpl.replace(/\{\{(\w+)\}\}/g, function (m, key) { 326 | // return { 327 | // date: allDocs[0].date 328 | // , entries: entries 329 | // }[key]; 330 | // }) 331 | // ; 332 | // wfs(pth.join(publishDir, "feed.atom"), atom); 333 | // 334 | // cb(); 335 | // } 336 | // 337 | // // build all the style related stuff 338 | // function buildStyle (cb) { 339 | // var finder = findit(styleDir); 340 | // finder.on("directory", copyTreeCB(__dirname)); 341 | // finder.on("file", function (file, stat) { 342 | // if (stat.ctime.getTime() <= lastRun) return; 343 | // if (pth.extname(file) === ".css") processCSS(file, pubPath(file, __dirname)); 344 | // else copyFile(file, pubPath(file, __dirname)); 345 | // }); 346 | // finder.on("end", cb); 347 | // } 348 | // 349 | // // build all the font related stuff 350 | // function buildFonts (cb) { 351 | // var finder = findit(fontsDir); 352 | // finder.on("directory", copyTreeCB(__dirname)); 353 | // finder.on("file", function (file, stat) { 354 | // if (stat.ctime.getTime() <= lastRun) return; 355 | // copyFile(file, pubPath(file, __dirname)); 356 | // }); 357 | // finder.on("end", cb); 358 | // } 359 | // 360 | // // build all the image related stuff 361 | // function buildImages (cb) { 362 | // var finder = findit(imgDir); 363 | // finder.on("directory", copyTreeCB(__dirname)); 364 | // finder.on("file", function (file, stat) { 365 | // if (stat.ctime.getTime() <= lastRun) return; 366 | // copyFile(file, pubPath(file, __dirname)); 367 | // }); 368 | // finder.on("end", cb); 369 | // } 370 | // 371 | // // set up icon stuff 372 | // function buildIcon (cb) { 373 | // copyFile(pth.join(__dirname, "favicon.png"), pth.join(publishDir, "favicon.png")); 374 | // cb(); 375 | // } 376 | // 377 | // // update log with current time 378 | // function updateLog (cb) { 379 | // wfs(timeLog, now); 380 | // wfs(imgJSON, JSON.stringify(randomCards, null, 4)); 381 | // cb(); 382 | // } 383 | // 384 | // // run it all 385 | // console.log("Publishing:"); 386 | // async.series( 387 | // [ 388 | // buildStyle 389 | // , buildFonts 390 | // , buildImages 391 | // , buildIcon 392 | // , buildContent 393 | // , buildIndex 394 | // , updateLog 395 | // ] 396 | // , function (err) { 397 | // if (err) console.error("BOOM!\n" + err); 398 | // console.log("OK!"); 399 | // } 400 | // ); 401 | // -------------------------------------------------------------------------------- /tools-src/build-site.js: -------------------------------------------------------------------------------- 1 | 2 | // load up Babel 3 | require("babel/polyfill"); 4 | 5 | let jn = require("path").join 6 | , rel = require("./utils/rel")(jn(__dirname, "..")) 7 | , contentDir = rel("content") 8 | , siteDir = rel("site") 9 | , sourceTree = require("./tasks/source-tree") 10 | , copyTree = require("./tasks/copy-tree") 11 | , copyStatic = require("./tasks/copy-static") 12 | , processHTML = require("./tasks/process-html") 13 | , buildProject = require("./tasks/build-project") 14 | , tree 15 | ; 16 | 17 | 18 | sourceTree(contentDir) 19 | .then((t) => { 20 | tree = t; 21 | }) 22 | .then(() => { return copyTree(siteDir, tree); }) 23 | .then(() => { return copyStatic(contentDir, siteDir, tree); }) 24 | .then(() => { return processHTML(contentDir, siteDir, tree); }) 25 | .then(() => { return buildProject(contentDir, siteDir, tree); }) 26 | .then(() => { 27 | console.log("Ok!"); 28 | }) 29 | .catch((err) => { 30 | console.error("BOOM", err); 31 | }) 32 | ; 33 | 34 | 35 | // build output directory tree 36 | // copy all non-HTML 37 | // process all HTML 38 | // - templates 39 | 40 | 41 | 42 | 43 | // var fs = require("fs-extra") 44 | // , pth = require("path") 45 | // , crypto = require("crypto") 46 | // , findit = require("findit") 47 | // , async = require("async") 48 | // , whacko = require("whacko") 49 | // , CleanCSS = require("clean-css") 50 | // // , nopt = require("nopt") 51 | // // , knownOpts = { 52 | // // "force": Boolean 53 | // // } 54 | // // , shortHands = { 55 | // // "f" : ["--force"] 56 | // // } 57 | // // , parsedOpt = nopt(knownOpts, shortHands) 58 | // , rel = function (to) { return pth.join(__dirname, to); } 59 | // , rfs = function (file) { return fs.readFileSync(file, "utf8"); } 60 | // , wfs = function (file, content) { fs.writeFileSync(file, content, { encoding: "utf8" }); } 61 | // , norm = function (str) { return str.replace(/\s+/g, " ").replace(/(^\s+|\s+$)/g, ""); } 62 | // , escAttr = function (str) { return str.replace(/&/g, "&").replace(/"/g, """); } 63 | // , escXML = function (str) { return str.replace(/&/g, "&").replace(/ Copying .............. " + output.replace(publishDir, "")); 94 | // fs.copySync(input, output); 95 | // } 96 | // 97 | // // process HTML source file 98 | // function processHTML (input, output) { 99 | // console.log("> Processing ........... " + output.replace(publishDir, "")); 100 | // var $ = whacko.load(rfs(input)) 101 | // , $tmpl = whacko.load(rfs(pth.join(tmplDir, "page.html"))) 102 | // , $html = $tmpl("html") 103 | // ; 104 | // // if ($("html").attr("skip")) return copyFile(input, output); 105 | // if ($("html").attr("skip")) return wfs(output, rfs(input).replace(/\s+skip=['"]?true['"]?/, "")); 106 | // var doc = { 107 | // lang: $("html").attr("lang") || "en" 108 | // , title: $("h1").html() 109 | // , subtitle: $("h2").html() 110 | // , date: $("html").attr("date") 111 | // , blurb: $("div.blurb").length ? $("div.blurb").html() : "

" + $("section > p").first().html() + "

" 112 | // , link: output.replace(publishDir, "").replace("index.html", "") 113 | // } 114 | // ; 115 | // doc.blurbText = $("div.blurb").text() || $("section > p").first().text(); 116 | // doc.url = "http://berjon.com" + doc.link; 117 | // 118 | // // head stuff 119 | // $html.attr("lang", doc.lang); 120 | // $html.find("title").text($("h1").text() + " | Robin Berjon"); 121 | // $html.find("link[rel=stylesheet]").attr("href", cssPath); 122 | // 123 | // // Twitter &FB cards 124 | // var title = $("h1").text() + " — " + $("h2").text(); 125 | // $html.find("meta[property='twitter:title']").attr("content", title); 126 | // $html.find("meta[property='og:title']").attr("content", title); 127 | // var desc = norm(escAttr(doc.blurbText)); 128 | // $html.find("meta[property='twitter:description']").attr("content", desc); 129 | // $html.find("meta[property='og:description']").attr("content", desc); 130 | // // XXX make this possibly use an image from the content or an attribute 131 | // if (!randomCards[doc.link]) 132 | // randomCards[doc.link] = "http://berjon.com/img/card-pics/" + cardImgs[Math.floor(Math.random() * cardImgs.length)] + ".jpg"; 133 | // $html.find("meta[property='twitter:image']").attr("content", randomCards[doc.link]); 134 | // $html.find("meta[property='og:image']").attr("content", randomCards[doc.link]); 135 | // $html.find("meta[property='twitter:url']").attr("content", doc.url); 136 | // $html.find("meta[property='og:url']").attr("content", doc.url); 137 | // $html.find("meta[property='og:locale']").attr("content", fbLocales[doc.lang]); 138 | // 139 | // // body 140 | // $html.find("h1").append($("h1").contents()); 141 | // $html.find("h2").append($("h2").contents()); 142 | // var tags = ($("html").attr("tags") || "No category") 143 | // .split(/\s*,\s*/) 144 | // .map(function (str) { 145 | // return str.charAt(0).toUpperCase() + str.slice(1); 146 | // }) 147 | // .join(", ") 148 | // , doList = tags !== "No category" 149 | // ; 150 | // $html.find("div.meta") 151 | // // .text(tags + " | ") 152 | // .append($("").text(doc.date)) 153 | // ; 154 | // // doc.tags = tags; 155 | // $html.find("article").append($("section")); 156 | // $html.find("q") 157 | // .each(function () { 158 | // var $span = $("").append($(this).contents()); 159 | // $(this) 160 | // .before("“") 161 | // .after("”") 162 | // .replaceWith($span) 163 | // ; 164 | // }) 165 | // ; 166 | // $html.find("p").last().append($("")); 167 | // var asides = 0 168 | // , $art = $html.find("article") 169 | // ; 170 | // $html.find("span.fn") 171 | // .each(function () { 172 | // asides++; 173 | // $(this).replaceWith($("" + asides + "")); 174 | // var $div = $("
" + asides + ".
"); 175 | // $div.append($(this).contents()); 176 | // $art.append($div); 177 | // }); 178 | // 179 | // if ($("html").attr("noindex")) doList = false; 180 | // if (doList) allDocs.push(doc); 181 | // wfs(output, $tmpl.html().replace(/&apos;/g, "'")); 182 | // } 183 | // 184 | // // process CSS source file 185 | // function processCSS (input, output) { 186 | // console.log("> CSS .................. " + output.replace(publishDir, "")); 187 | // var css = rfs(input) 188 | // , cssmin = new CleanCSS({ 189 | // keepSpecialComments: 0 190 | // , root: __dirname 191 | // , relativeTo: styleDir 192 | // , processImport: true 193 | // , noAdvanced: true 194 | // }) 195 | // , minned = cssmin.minify(css) 196 | // , hash = crypto.createHash("md5").update(minned).digest("hex") 197 | // ; 198 | // output = pth.join(pth.dirname(output), hash + ".css"); 199 | // cssPath = "/css/" + hash + ".css"; 200 | // wfs(output, minned); 201 | // } 202 | // 203 | // // finder callback to copy directory tree 204 | // function copyTreeCB (trimDir) { 205 | // return function (dir, stat) { 206 | // if (stat.ctime.getTime() <= lastRun) return; 207 | // var toPub = pubPath(dir, trimDir); 208 | // console.log("> Creating directory ... " + (toPub.replace(publishDir, "") || "/")); 209 | // fs.mkdirpSync(toPub); 210 | // }; 211 | // } 212 | // 213 | // // find everything that has been modified since last time 214 | // function buildContent (cb) { 215 | // var finder = findit(contentDir); 216 | // finder.on("directory", copyTreeCB()); 217 | // finder.on("file", function (file, stat) { 218 | // if (stat.ctime.getTime() <= lastRun) return; 219 | // if (pth.extname(file) === ".html") processHTML(file, pubPath(file)); 220 | // else copyFile(file, pubPath(file)); 221 | // }); 222 | // finder.on("end", cb); 223 | // } 224 | // 225 | // // produce an index body from a list of docs 226 | // function listDocs (docs) { 227 | // var $item = whacko.load(rfs(pth.join(tmplDir, "index-item.html"))) 228 | // , list = "" 229 | // ; 230 | // 231 | // docs.forEach(function (doc) { 232 | // var $art = $item("article").clone() 233 | // , $a = $item("") 234 | // ; 235 | // $art.attr("lang", doc.lang); 236 | // $a.attr("href", doc.link).html(doc.title); 237 | // $art.find("h1").append($a); 238 | // $art.find("h2").html(doc.subtitle); 239 | // $art.find("div.meta") 240 | // // .text(doc.tags + " | ") 241 | // .append($item("").text(doc.date)) 242 | // ; 243 | // $art.append(doc.blurb); 244 | // $art.find("p img").each(function () { 245 | // var $img = $item(this) 246 | // , src = $img.attr("src") 247 | // ; 248 | // if (/^https?:/i.test(src)) return; 249 | // if (/\.\./.test(src)) return; 250 | // if (/^\//.test(src)) return; 251 | // $img.attr("src", doc.link + src); 252 | // }); 253 | // list += "
\n" + $art.html() + "\n
\n"; 254 | // }); 255 | // return list; 256 | // } 257 | // 258 | // // produce an index document 259 | // function makeIndex (data) { 260 | // var $tmpl = whacko.load(rfs(pth.join(tmplDir, "index.html"))) 261 | // , $html = $tmpl("html") 262 | // ; 263 | // $html.attr("lang", data.lang); 264 | // $html.find("title").text(data.title); 265 | // $html.find("link[rel=stylesheet]").attr("href", cssPath); 266 | // $html.find("main").html(data.body); 267 | // $html.find("main").after($tmpl(data.years)); 268 | // return $tmpl.html(); 269 | // } 270 | // 271 | // 272 | // // build the index stuff 273 | // function buildIndex (cb) { 274 | // allDocs.sort(function (a, b) { 275 | // if (a.date < b.date) return 1; 276 | // if (a.date > b.date) return -1; 277 | // return 0; 278 | // }); 279 | // 280 | // // list every year, and for each produce its index 281 | // var years = {}; 282 | // allDocs.forEach(function (doc) { 283 | // var year = doc.date.replace(/^(\d{4}).*/, "$1"); 284 | // if (!years[year]) years[year] = []; 285 | // years[year].push(doc); 286 | // }); 287 | // var allYears = "
    " + 288 | // Object.keys(years) 289 | // .sort() 290 | // .map(function (year) { 291 | // return "
  • " + year + "
  • "; 292 | // }) 293 | // .join("\n") + 294 | // "
" 295 | // ; 296 | // for (var year in years) { 297 | // console.log("> Generating index for year " + year); 298 | // fs.mkdirpSync(pth.join(publishDir, year)); 299 | // wfs(pth.join(publishDir, year, "index.html"), makeIndex({ 300 | // title: "Robin Berjon articles in " + year 301 | // , lang: "en" 302 | // , body: listDocs(years[year]) 303 | // , years: allYears 304 | // })); 305 | // } 306 | // 307 | // // most recent 30 on root index 308 | // console.log("> Generating front index"); 309 | // var root = { 310 | // title: "Robin Berjon" 311 | // , lang: "en" 312 | // , body: listDocs(allDocs.slice(0, 30)) 313 | // , years: allYears 314 | // } 315 | // ; 316 | // wfs(pth.join(publishDir, "index.html"), makeIndex(root)); 317 | // 318 | // // Atom 319 | // var atomTmpl = rfs(pth.join(tmplDir, "feed.atom")) 320 | // , entryTmpl = rfs(pth.join(tmplDir, "entry.atom")) 321 | // , entries = allDocs 322 | // .slice(0, 30) 323 | // .map(function (doc) { 324 | // return entryTmpl.replace(/\{\{(\w+)\}\}/g, function (m, key) { 325 | // return escXML(doc[key]) || "XXX"; 326 | // }); 327 | // }) 328 | // .join("\n") 329 | // , atom = atomTmpl.replace(/\{\{(\w+)\}\}/g, function (m, key) { 330 | // return { 331 | // date: allDocs[0].date 332 | // , entries: entries 333 | // }[key]; 334 | // }) 335 | // ; 336 | // wfs(pth.join(publishDir, "feed.atom"), atom); 337 | // 338 | // cb(); 339 | // } 340 | // 341 | // // build all the style related stuff 342 | // function buildStyle (cb) { 343 | // var finder = findit(styleDir); 344 | // finder.on("directory", copyTreeCB(__dirname)); 345 | // finder.on("file", function (file, stat) { 346 | // if (stat.ctime.getTime() <= lastRun) return; 347 | // if (pth.extname(file) === ".css") processCSS(file, pubPath(file, __dirname)); 348 | // else copyFile(file, pubPath(file, __dirname)); 349 | // }); 350 | // finder.on("end", cb); 351 | // } 352 | // 353 | // // build all the font related stuff 354 | // function buildFonts (cb) { 355 | // var finder = findit(fontsDir); 356 | // finder.on("directory", copyTreeCB(__dirname)); 357 | // finder.on("file", function (file, stat) { 358 | // if (stat.ctime.getTime() <= lastRun) return; 359 | // copyFile(file, pubPath(file, __dirname)); 360 | // }); 361 | // finder.on("end", cb); 362 | // } 363 | // 364 | // // build all the image related stuff 365 | // function buildImages (cb) { 366 | // var finder = findit(imgDir); 367 | // finder.on("directory", copyTreeCB(__dirname)); 368 | // finder.on("file", function (file, stat) { 369 | // if (stat.ctime.getTime() <= lastRun) return; 370 | // copyFile(file, pubPath(file, __dirname)); 371 | // }); 372 | // finder.on("end", cb); 373 | // } 374 | // 375 | // // set up icon stuff 376 | // function buildIcon (cb) { 377 | // copyFile(pth.join(__dirname, "favicon.png"), pth.join(publishDir, "favicon.png")); 378 | // cb(); 379 | // } 380 | // 381 | // // update log with current time 382 | // function updateLog (cb) { 383 | // wfs(timeLog, now); 384 | // wfs(imgJSON, JSON.stringify(randomCards, null, 4)); 385 | // cb(); 386 | // } 387 | // 388 | // // run it all 389 | // console.log("Publishing:"); 390 | // async.series( 391 | // [ 392 | // buildStyle 393 | // , buildFonts 394 | // , buildImages 395 | // , buildIcon 396 | // , buildContent 397 | // , buildIndex 398 | // , updateLog 399 | // ] 400 | // , function (err) { 401 | // if (err) console.error("BOOM!\n" + err); 402 | // console.log("OK!"); 403 | // } 404 | // ); 405 | // 406 | -------------------------------------------------------------------------------- /site/img/tree.svg: -------------------------------------------------------------------------------- 1 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | 128 | 129 | 130 | 131 | 132 | 133 | 134 | 135 | 136 | 137 | 138 | 139 | 140 | 141 | 142 | 143 | 144 | 145 | 146 | 147 | 148 | 149 | 150 | 151 | 152 | 153 | 154 | 155 | 156 | 157 | 158 | 159 | 160 | 161 | 162 | 163 | 164 | 165 | 166 | 167 | 168 | 169 | 170 | 171 | 172 | 173 | 174 | 175 | 176 | 177 | 178 | 179 | 180 | 181 | 182 | 183 | 184 | 185 | 186 | 187 | 188 | 189 | 190 | 191 | 192 | 193 | 194 | 195 | 196 | 197 | 198 | 199 | 200 | 201 | 202 | 203 | 204 | 205 | 206 | 207 | 208 | 209 | 210 | 211 | 212 | 213 | 214 | 215 | 216 | 217 | 218 | 219 | 220 | 221 | 222 | 223 | 224 | 225 | 226 | 227 | 228 | 229 | 230 | 231 | 232 | 233 | 234 | 235 | 236 | 237 | 238 | 239 | 240 | 241 | 242 | 243 | 244 | 245 | 246 | 247 | 248 | 249 | 250 | 251 | 252 | 253 | 254 | 255 | 256 | 257 | 258 | 259 | 260 | 261 | 262 | 263 | 264 | 265 | 266 | 267 | 268 | 269 | 270 | 271 | 272 | 273 | 274 | 275 | 276 | 277 | 278 | 279 | 280 | 281 | 282 | 283 | 284 | 285 | 286 | 287 | 288 | 289 | 290 | 291 | 292 | 293 | 294 | 295 | 296 | 297 | 298 | 299 | 300 | 301 | 302 | 303 | 304 | 305 | 306 | 307 | 308 | 309 | 310 | 311 | 312 | 313 | 314 | 315 | 316 | 317 | 318 | 319 | 320 | 321 | 322 | 323 | 324 | 325 | 326 | 327 | 328 | 329 | 330 | 331 | 332 | 333 | 334 | 335 | 336 | 337 | 338 | 339 | 340 | 341 | 342 | 343 | 344 | 345 | 346 | 347 | 348 | 349 | 350 | 351 | 352 | 353 | 354 | 355 | 356 | 357 | 358 | 359 | 360 | 361 | 362 | 363 | 364 | 365 | 366 | 367 | 368 | 369 | 370 | 371 | 372 | 373 | 374 | 375 | 376 | 377 | 378 | 379 | 380 | 381 | 382 | 383 | 384 | 385 | 386 | 387 | 388 | 389 | 390 | 391 | 392 | 393 | 394 | -------------------------------------------------------------------------------- /content/img/tree.svg: -------------------------------------------------------------------------------- 1 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | 128 | 129 | 130 | 131 | 132 | 133 | 134 | 135 | 136 | 137 | 138 | 139 | 140 | 141 | 142 | 143 | 144 | 145 | 146 | 147 | 148 | 149 | 150 | 151 | 152 | 153 | 154 | 155 | 156 | 157 | 158 | 159 | 160 | 161 | 162 | 163 | 164 | 165 | 166 | 167 | 168 | 169 | 170 | 171 | 172 | 173 | 174 | 175 | 176 | 177 | 178 | 179 | 180 | 181 | 182 | 183 | 184 | 185 | 186 | 187 | 188 | 189 | 190 | 191 | 192 | 193 | 194 | 195 | 196 | 197 | 198 | 199 | 200 | 201 | 202 | 203 | 204 | 205 | 206 | 207 | 208 | 209 | 210 | 211 | 212 | 213 | 214 | 215 | 216 | 217 | 218 | 219 | 220 | 221 | 222 | 223 | 224 | 225 | 226 | 227 | 228 | 229 | 230 | 231 | 232 | 233 | 234 | 235 | 236 | 237 | 238 | 239 | 240 | 241 | 242 | 243 | 244 | 245 | 246 | 247 | 248 | 249 | 250 | 251 | 252 | 253 | 254 | 255 | 256 | 257 | 258 | 259 | 260 | 261 | 262 | 263 | 264 | 265 | 266 | 267 | 268 | 269 | 270 | 271 | 272 | 273 | 274 | 275 | 276 | 277 | 278 | 279 | 280 | 281 | 282 | 283 | 284 | 285 | 286 | 287 | 288 | 289 | 290 | 291 | 292 | 293 | 294 | 295 | 296 | 297 | 298 | 299 | 300 | 301 | 302 | 303 | 304 | 305 | 306 | 307 | 308 | 309 | 310 | 311 | 312 | 313 | 314 | 315 | 316 | 317 | 318 | 319 | 320 | 321 | 322 | 323 | 324 | 325 | 326 | 327 | 328 | 329 | 330 | 331 | 332 | 333 | 334 | 335 | 336 | 337 | 338 | 339 | 340 | 341 | 342 | 343 | 344 | 345 | 346 | 347 | 348 | 349 | 350 | 351 | 352 | 353 | 354 | 355 | 356 | 357 | 358 | 359 | 360 | 361 | 362 | 363 | 364 | 365 | 366 | 367 | 368 | 369 | 370 | 371 | 372 | 373 | 374 | 375 | 376 | 377 | 378 | 379 | 380 | 381 | 382 | 383 | 384 | 385 | 386 | 387 | 388 | 389 | 390 | 391 | 392 | 393 | 394 | --------------------------------------------------------------------------------