Skip to content

Instantly share code, notes, and snippets.

Rich-Harris /
Last active August 29, 2015 13:56 — forked from wuub/
import sublime, sublime_plugin
BUILD_COLOR_SCHEME = "Packages/Color Scheme - Default/Dawn.tmTheme"
def in_build_dir(view):
if not view or not view.file_name():
return False
return "/build/" in view.file_name()
Rich-Harris /
Last active August 29, 2015 13:56
AMD loaders that use local resources during optimisation, but CDN resources in production - possible?

So I have an AMD loader, which ingests HTML files that define Ractive.js components (think HTML imports describing Web Components - it's fairly similar in concept). Similar to @jrburke's Element loader. The discussion around the Ractive single-file-components spec is here, if anyone is interested.

The loader itself isn't currently online but will be in the near future.

Here's the issue: we have several different apps sharing a single page (these are interactive components within a news article), several of which use this loader. There's no sense in including Ractive with each optimised build, so in common with other libraries that are shared by several components (e.g. jQuery and d3) it is excluded from the optimised build and served from a CDN.

The problem is that the loader needs Ractive during the optimisation process, to parse the HTML files into a form it can work with. Because of this

Rich-Harris /
Created February 26, 2014 18:32
rvc.js output

This is a sample output from rvc.js to aid development of an equivalent browserify transform (see this GitHub thread). It's been commented and cleaned up slightly for readability - i.e. indenting etc.

The source file is this:


  // first, we get the parsed template, JSON.stringified css, and any
  // child components that this component uses
  var __options__={
Rich-Harris / Evaluating
Last active August 29, 2015 13:57
Evaluating expressions within events

In answer to this tweet:

Within Ractive templates, you can use normal JavaScript expressions (with a handful of exceptions, e.g. no new operators or assignments, since expressions should be side-effect free). These expressions aren't straightforwardly evaled - instead, they're parsed into an abstract syntax tree, at which point we extract the references and turn it back into a string which is later used to generate a function:

Ractive.parse('{{ a+b+1 ? "a" : "b" }}');

// results in
 t: 2,
Rich-Harris /
Created May 28, 2014 18:51
Rx adaptor

Following on from this conversation...

Ractive.js is a library for building reactive user interfaces. Unlike systems that are based on library-specific event-emitting model classes (e.g. Backbone.Model, ko.observable et al) or observable values, Ractive is based on POJOs and keypaths:

ractive.set('user', {
  name: 'Alice',
  age: 42
Rich-Harris /
Created August 8, 2014 14:54
Using ractive.runtime.js

If you're able to parse templates on the server, or as part of a build process, you can use ractive.runtime.js instead of ractive.js in your app. It's slightly smaller, and it means that browsers are spared having to parse templates on the client (though this is a very quick process for all but the most complex templates).

In effect, instead of doing this...

var ractive = new Ractive({
  el: 'body',
  template: '<h1>Hello {{name}}!</h1>',
  data: { name: 'world' }
Rich-Harris /
Last active August 29, 2015 14:05
Why I defected from Broccoli

This is in answer to @ebryn's tweet:

Having written Gobble, I want to make it plain that I'm actually a big Broccoli fan - I've extolled its virtues far and wide, and we used it at and with Ractive for some time. My appreciation has only increased since discovering how bloody awkward it is to deal with the filesystem for anything non-trivial (and I thought web development was fraught). I'm fully aware that there are areas where Broccoli easily beats Gobble (e.g. Windows support), and that it's far more battle-tested.

But there are things about Broccoli that grated, and which eventually drove me to create a replacement.

Weird, hard to reproduce errors

We used Broccoli on a large and complex project at the Guardian recently. As it grew, we started to get strange errors, e.g. ENOENT errors on files that Broccoli was supposed to be managing. Although these could be fixed by just restarting Broccoli, i

Rich-Harris / getKeypath.js
Last active August 29, 2015 14:06
Keypath object idea
import normaliseKeypath from 'shared/normaliseKeypath';
var cache = {}, Keypath;
Keypath = function ( str ) {
this.str = str;
this.keys = this.str.split( '.' );
this.last = this.keys[ this.keys.length - 1 ];
Rich-Harris / copy.js
Last active August 29, 2015 14:06
Gobble copy transform
// warning: i haven't tested this! it's using
module.exports = function copy ( inputdir, outputdir, options, callback, errback ) {
var fs = require( 'fs-extra' );
fs.copy( inputdir, outputdir, function ( err ) {
if ( err ) {
errback( err );
} else {
Rich-Harris /
Last active August 29, 2015 14:06
Setting up event handlers and observers in a Ractive component

In response to this tweet

You can do any setup work (binding to events, observing data) inside an init() function:

Widget = Ractive.extend({
  template: '...',
  init: function () {
    this.on( 'someEvent', someEventHandler );