Skip to content

Commit

Permalink
refactor of the entire build process to work with babel and rollup. g…
Browse files Browse the repository at this point in the history
…runt is now only used for 262, the rest are just npm commands.
  • Loading branch information
caridy committed Feb 29, 2016
1 parent 5a22b1e commit 07155a7
Show file tree
Hide file tree
Showing 11 changed files with 339 additions and 429 deletions.
20 changes: 12 additions & 8 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,35 +14,39 @@ To run the unit tests:

To build files in `dist/` and `lib/`:

grunt
npm run build


Updating CLDR Data
------------------

_Note: this step is completely optional._
To specifically build files in `locale-data`:

Copy fresh CLDR data in `data/`:
npm run build:data

grunt update-cldr-data
Note: this is completely optional since the regular `npm run build` will take care of it.

To build files in `locale-data/` based on CLDR `data/`:
Updating Test 262
-----------------

To specifically build files in `tests/test262`:

grunt cldr
grunt update-test262

Note: be careful when attempting to update the tests.

Source Code
-----------

All the source code is in `src/` folder, written as ES6 modules, and transpiled
using `es6-module-transpiler` into the `lib/` and `dist/` folders.
using `rollup` and `babel` into the `lib/` and `dist/` folders.

The `dist/` is in git because of bower, make sure you commit those files as well.

Release checklist
-----------------

* build all files using `grunt`
* build all files using `npm run build`
* run all tests using `npm test`
* verify that [README.md] is updated
* bump the version in [package.json]
Expand Down
64 changes: 2 additions & 62 deletions Gruntfile.js
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
// This file is only needed to update test 262 used to test this polyfill
// by using the command: `$ grunt update-test262`
module.exports = function (grunt) {

grunt.initConfig({
pkg: grunt.file.readJSON('package.json'),

clean: {
cldr : ['locale-data/'],
test262: ['tmp/test262**', 'data/test262**', 'tests/test262/'],
lib : ['lib/', 'dist/'],
},

curl: {
Expand All @@ -17,10 +17,6 @@ module.exports = function (grunt) {
},

unzip: {
cldr: {
src : 'tmp/cldr.zip',
dest: 'tmp/cldr/',
},
test262: {
src : 'tmp/test262.zip',
dest: 'tmp/',
Expand All @@ -38,72 +34,16 @@ module.exports = function (grunt) {
'harness/*.js',
],
},
src: {
expand : true,
flatten: true,
src : ['tmp/src/*.js'],
dest : 'lib/',
},
},

concat: {
complete: {
src : ['dist/Intl.min.js', 'locale-data/complete.js'],
dest: 'dist/Intl.complete.js',
},
},

jshint: {
options: {
eqeqeq: true,
},
src: ['src/*.js'],
node: ['index.js', '*.json'],
build: ['tasks/**/*.js'],
},

bundle_jsnext: {
dest: 'dist/Intl.js',
options: {
namespace: 'IntlPolyfill',
},
},

cjs_jsnext: {
dest: 'tmp/',
},

uglify: {
options: {
preserveComments: 'some',
},
build: {
files: {
'dist/Intl.min.js': ['dist/Intl.js'],
},
},
},

});

grunt.loadTasks('./tasks');
grunt.loadNpmTasks('grunt-contrib-clean');
grunt.loadNpmTasks('grunt-contrib-copy');
grunt.loadNpmTasks('grunt-contrib-concat');
grunt.loadNpmTasks('grunt-contrib-jshint');
grunt.loadNpmTasks('grunt-contrib-uglify');
grunt.loadNpmTasks('grunt-bundle-jsnext-lib');
grunt.loadNpmTasks('grunt-curl');
grunt.loadNpmTasks('grunt-zip');

grunt.registerTask('build', [
'bundle_jsnext', 'uglify', 'cjs_jsnext', 'copy:src', 'concat:complete',
]);

grunt.registerTask('cldr', ['clean:cldr', 'extract-cldr-data', 'compile-data']);

grunt.registerTask('default', ['jshint', 'clean:lib', 'build']);

grunt.registerTask('update-test262', [
'clean:test262',
'curl:test262',
Expand Down
28 changes: 11 additions & 17 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@
"version": "1.1.0",
"description": "Polyfill the ECMA-402 Intl API (except collation)",
"main": "index.js",
"jsnext:main": "src/main.js",
"directories": {
"test": "tests"
},
Expand All @@ -13,8 +12,8 @@
},
"devDependencies": {
"async": "^0.9.0",

"babel-cli": "^6.2.0",
"babel-eslint": "^5.0.0",
"babel-plugin-transform-es2015-modules-commonjs": "^6.4.0",
"babel-plugin-transform-es3-member-expression-literals": "^6.3.13",
"babel-plugin-transform-es3-property-literals": "^6.3.13",
Expand All @@ -23,16 +22,6 @@
"babel-preset-es2015": "^6.1.18",
"babel-preset-es2015-rollup": "^1.1.1",
"babel-register": "^6.2.0",
"rimraf": "^2.4.2",
"rollup": "^0.25.0",
"rollup-plugin-babel": "^2.3.9",
"rollup-plugin-commonjs": "^2.2.0",
"rollup-plugin-memory": "^1.0.0",
"rollup-plugin-npm": "^1.3.0",
"rollup-plugin-replace": "^1.1.0",
"rollup-plugin-uglify": "^0.1.0",

"babel-eslint": "^5.0.0",
"cldr-cal-buddhist-full": "28.0.0",
"cldr-cal-chinese-full": "28.0.0",
"cldr-cal-coptic-full": "28.0.0",
Expand All @@ -53,17 +42,22 @@
"finalhandler": "^0.4.0",
"glob": "^5.0.3",
"grunt": "^0.4.5",
"grunt-bundle-jsnext-lib": "^0.5.0",
"grunt-cli": "~0.1.13",
"grunt-contrib-clean": "^0.6.0",
"grunt-contrib-concat": "^0.5.0",
"grunt-contrib-copy": "^0.5.0",
"grunt-contrib-jshint": "^0.10.0",
"grunt-contrib-uglify": "^0.5.1",
"grunt-curl": "^2.1.0",
"grunt-zip": "^0.16.2",
"jshint": "^2.5.5",
"mkdirp": "^0.5.1",
"object.assign": "^1.1.1",
"rimraf": "^2.4.2",
"rollup": "^0.25.0",
"rollup-plugin-babel": "^2.3.9",
"rollup-plugin-commonjs": "^2.2.0",
"rollup-plugin-memory": "^1.0.0",
"rollup-plugin-npm": "^1.3.0",
"rollup-plugin-replace": "^1.1.0",
"rollup-plugin-uglify": "^0.1.0",
"sauce-tunnel": "^2.2.3",
"serve-static": "^1.10.0",
"wd": "^0.3.6"
Expand All @@ -75,7 +69,7 @@
"build:dist:dev": "NODE_ENV=development babel-node scripts/build-dist",
"build:dist:prod": "NODE_ENV=production babel-node scripts/build-dist",
"build:dist": "npm run build:dist:dev && npm run build:dist:prod",
"build": "npm run build:lib && npm run build:dist",
"build": "npm run build:data && npm run build:lib && npm run build:dist",
"lint": "eslint .",
"test": "cd tests && node noderunner.js && node saucelabs.js",
"pretest": "npm run lint",
Expand Down
167 changes: 167 additions & 0 deletions scripts/build-data.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,167 @@
/* global Promise */
import * as fs from 'fs';
import * as p from 'path';
import {sync as mkdirpSync} from 'mkdirp';

function writeFile(filename, contents) {
return new Promise((resolve, reject) => {
fs.writeFile(filename, contents, (err) => {
if (err) {
reject(err);
} else {
resolve(p.resolve(filename));
}
});
});
}

function mergeData(...sources) {
return sources.reduce((data, source) => {
Object.keys(source || {}).forEach((locale) => {
data[locale] = Object.assign(data[locale] || {}, source[locale]);
});

return data;
}, {});
}

function reviver (k, v) {
let idx;

if (k === 'locale')
return v;

else if (typeof v === 'string') {
idx = prims.indexOf(v);
valCount++;

if (idx === -1)
idx += prims.push(v);

return '###prims['+ idx +']###';
}

else if (typeof v === 'object' && v !== null) {
const str = JSON.stringify(v);
objCount++;

if (objStrs.hasOwnProperty(str))
return objStrs[str];

// We need to make sure this object is not added to the same
// array as an object it references (and we need to check
// this recursively)
let depth;
let objDepths = [0];

for (let key in v) {
if (typeof v[key] === 'string' && (depth = v[key].match(/^###objs\[(\d+)/)))
objDepths.push(+depth[1] + 1);
}

depth = Math.max.apply(Math, objDepths);

if (!Array.isArray(objs[depth]))
objs[depth] = [];

idx = objs[depth].push(v) - 1;
objStrs[str] = '###objs['+ depth +']['+ idx +']###';

return objStrs[str];
}

return v;
}

// -----------------------------------------------------------------------------

mkdirpSync('locale-data/');
mkdirpSync('locale-data/json/');
mkdirpSync('locale-data/jsonp/');

// extracting data into CLDR

// Regex for converting locale JSON to object grammar, obviously simple and
// incomplete but should be good enough for the CLDR JSON
const jsonpExp = /"(?!default)([\w$][\w\d$]+)":/g;

import reduceLocaleData from './utils/reduce';

import extractCalendars from './utils/extract-calendars';
import extractNumbersFields from './utils/extract-numbers';
import {getAllLocales} from './utils/locales';

// Default to all CLDR locales.
const locales = getAllLocales();

// Each type of data has the structure: `{"<locale>": {"<key>": <value>}}`,
// which is well suited for merging into a single object per locale. This
// performs that deep merge and returns the aggregated result.
let locData = mergeData(
extractCalendars(locales),
extractNumbersFields(locales)
);

let locStringData = {};

Object.keys(locData).forEach((locale) => {
// Ignore en-US-POSIX and root
if (locale.toLowerCase() === 'en-us-posix') {
return;
}

const obj = reduceLocaleData(locale, locData[locale]);
locStringData[locale] = JSON.stringify(obj, null, 4);
const jsonpContent = `IntlPolyfill.__addLocaleData(${JSON.stringify(obj).replace(jsonpExp, '$1:')});`;
writeFile('locale-data/json/' + locale + '.json', locStringData[locale]);
writeFile('locale-data/jsonp/' + locale + '.js', jsonpContent);
});

console.log('Total number of locales is ' + Object.keys(locData).length);

// compiling `locale-date/complete.js`

function replacer($0, type, loc) {
return (type === 'prims' ? 'a' : 'b') + loc;
}

let
objStrs = {},
objs = [],
prims = [],

valCount = 0,
objCount = 0,

fileData = '';

fileData += '(function(addLocaleData){\n';

let locReducedData = {};
Object.keys(locStringData).forEach((k) => {
const c = locStringData[k];
locReducedData[k] = JSON.parse(c, reviver);
});

fileData += `var a=${JSON.stringify(prims)},b=[];`;
objs.forEach((val, idx) => {
const ref = JSON.stringify(val).replace(/"###(objs|prims)(\[[^#]+)###"/g, replacer);

fileData += `b[${idx}]=${ref};`;
});

for (let k in locReducedData) {
fileData += `addLocaleData(${locReducedData[k].replace(/###(objs|prims)(\[[^#]+)###/, replacer)});
`;
}

fileData += `})(IntlPolyfill.__addLocaleData);`;

// writting the complete optimized bundle
writeFile('locale-data/complete.js', fileData);

console.log('Total number of reused strings is ' + prims.length + ' (reduced from ' + valCount + ')');
console.log('Total number of reused objects is ' + Object.keys(objStrs).length + ' (reduced from ' + objCount + ')');

process.on('unhandledRejection', (reason) => {throw reason;});
console.log('Writing locale data files...');
Loading

0 comments on commit 07155a7

Please sign in to comment.