When all you have is a hammer, everything looks like Javascript - ebookcraft 2015 - Baldur Bjarnason

Post on 06-Aug-2015

219 views 2 download

transcript

When all you have is a hammer, everything looks

like JavaScript

I’m Baldur BjarnasonMy job at Unbound is to, over time, automate everything

that can be automated about our ebook production

My goal is to convince you of two things

• That software projects should start small and scale up

• That Javascript is the tool for the job

Javascript all the things!

Alternate title for this talk…

Really? That can’t be a good idea.

Tool-buying versus

Tool-making

Tool-making starts small

Small, hacky solutions build up to larger things

The case for javascript

JS is web nativeIt mixes well with HTML and CSS

JS as a skill is eminently reusable

Used in browsers, app automation, servers, plugins, mobile apps, you name it

node.jsJavascript without the browser mess

https://nodejs.org

Node.js

• Opens up the possibility of standalone scripts

• No browser necessary

• Modularity let’s you start small and add as you iterate

Node.js makes javascript fun

The laws of software development

Gall’s law"A complex system that works is invariably found to have evolved from a simple system that worked. The inverse proposition also appears to be true: A complex system designed from scratch never works and cannot be made to work. You have to start over, beginning with a working simple system."

Let’s start off by taking something BBedit does

well and do it badly

var fs = require("fs"); var glob = require(‘glob’); var files = glob.sync(‘*.html’);

bodyre = new RegExp('(<h1[^>]*>|</h1>)', 'ig');

files.forEach(function(textname) { var text = fs.readFileSync(textname, "utf8"); var title = text.split(bodyre)[2]; console.log(title); });

The limits of Regular Expressions

<[^<>/]*?class=\”random-class-thing"[^<>/]*?>)([^<>]*?)(</[^<>/]*?>

versus

document.querySelectorAll('random-class-thing');

var fs = require("fs");

var jsdom = require("jsdom");

var jquery = require("jquery");

book = fs.readFileSync("eBook Test-5March14.html", "utf8");

jsdom.env({

html: book,

done: function (errors, window) {

jquery(window);

window.$("h4").unwrap();

window.$("h1").addClass("test2");

fs.writeFileSync("bookbody3.html", window.document.documentElement.innerHTML);

}

});

The tool-making bit:#!/usr/bin/env node

'use strict'; var program = require(‘commander'); program.version('0.1.0') .option('-f, --folder [path]', 'Output folder') .option('-o, --output [filename]', 'Filename') .option('-v, --verbose', "Let's be chatty and loud") .option('-m, --mangle', 'Obfuscate the font files');

Are we having fun yet?

The recipe for success

• One part hacky node.js scripts

• One part commander (or similar module)

• Mix well over time

• And the result…

Tools!

var mangler = function(fontpath, id) {

var font = fs.readFileSync(fontpath);

var shasum = crypto.createHash('sha1').update(id.trim(), 'utf8');

var key = new Buffer(shasum.digest('hex'), 'hex');

var prefix = font.slice(0, 1040);

var _fn = function(blob, i) { return prefix[i] = blob ^ key[i % key.length]; };

for (i = _i = 0, _len = prefix.length; _i < _len; i = ++_i) {

var blob = prefix[i];

_fn(blob, i);

}

font2 = Buffer.concat([prefix, font.slice(1040)]);

fs.writeFileSync(fontpath, font2);

};

That was a kick in the faceBut can you guess what it was for?

Learning JS

• Mozilla’s re-introduction to JavaScript: https://developer.mozilla.org/en-US/docs/Web/JavaScript/A_re-introduction_to_JavaScript

• Eloquent JavaScript http://eloquentjavascript.net

• JavaScript: The Good Parts by Douglas Crockford

Learning JS

• Khan Academy: http://www.khanacademy.org/computing/computer-programming

• Codecademy: http://www.codecademy.com/tracks/javascript