Skip to content
This repository was archived by the owner on Apr 14, 2021. It is now read-only.

Commit 07155a7

Browse files
committed
refactor of the entire build process to work with babel and rollup. grunt is now only used for 262, the rest are just npm commands.
1 parent 5a22b1e commit 07155a7

11 files changed

+339
-429
lines changed

CONTRIBUTING.md

+12-8
Original file line numberDiff line numberDiff line change
@@ -14,35 +14,39 @@ To run the unit tests:
1414

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

17-
grunt
17+
npm run build
1818

1919

2020
Updating CLDR Data
2121
------------------
2222

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

25-
Copy fresh CLDR data in `data/`:
25+
npm run build:data
2626

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

29-
To build files in `locale-data/` based on CLDR `data/`:
29+
Updating Test 262
30+
-----------------
31+
32+
To specifically build files in `tests/test262`:
3033

31-
grunt cldr
34+
grunt update-test262
3235

36+
Note: be careful when attempting to update the tests.
3337

3438
Source Code
3539
-----------
3640

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

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

4246
Release checklist
4347
-----------------
4448

45-
* build all files using `grunt`
49+
* build all files using `npm run build`
4650
* run all tests using `npm test`
4751
* verify that [README.md] is updated
4852
* bump the version in [package.json]

Gruntfile.js

+2-62
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,12 @@
1+
// This file is only needed to update test 262 used to test this polyfill
2+
// by using the command: `$ grunt update-test262`
13
module.exports = function (grunt) {
24

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

68
clean: {
7-
cldr : ['locale-data/'],
89
test262: ['tmp/test262**', 'data/test262**', 'tests/test262/'],
9-
lib : ['lib/', 'dist/'],
1010
},
1111

1212
curl: {
@@ -17,10 +17,6 @@ module.exports = function (grunt) {
1717
},
1818

1919
unzip: {
20-
cldr: {
21-
src : 'tmp/cldr.zip',
22-
dest: 'tmp/cldr/',
23-
},
2420
test262: {
2521
src : 'tmp/test262.zip',
2622
dest: 'tmp/',
@@ -38,72 +34,16 @@ module.exports = function (grunt) {
3834
'harness/*.js',
3935
],
4036
},
41-
src: {
42-
expand : true,
43-
flatten: true,
44-
src : ['tmp/src/*.js'],
45-
dest : 'lib/',
46-
},
47-
},
48-
49-
concat: {
50-
complete: {
51-
src : ['dist/Intl.min.js', 'locale-data/complete.js'],
52-
dest: 'dist/Intl.complete.js',
53-
},
54-
},
55-
56-
jshint: {
57-
options: {
58-
eqeqeq: true,
59-
},
60-
src: ['src/*.js'],
61-
node: ['index.js', '*.json'],
62-
build: ['tasks/**/*.js'],
63-
},
64-
65-
bundle_jsnext: {
66-
dest: 'dist/Intl.js',
67-
options: {
68-
namespace: 'IntlPolyfill',
69-
},
70-
},
71-
72-
cjs_jsnext: {
73-
dest: 'tmp/',
74-
},
75-
76-
uglify: {
77-
options: {
78-
preserveComments: 'some',
79-
},
80-
build: {
81-
files: {
82-
'dist/Intl.min.js': ['dist/Intl.js'],
83-
},
84-
},
8537
},
8638

8739
});
8840

8941
grunt.loadTasks('./tasks');
9042
grunt.loadNpmTasks('grunt-contrib-clean');
9143
grunt.loadNpmTasks('grunt-contrib-copy');
92-
grunt.loadNpmTasks('grunt-contrib-concat');
93-
grunt.loadNpmTasks('grunt-contrib-jshint');
94-
grunt.loadNpmTasks('grunt-contrib-uglify');
95-
grunt.loadNpmTasks('grunt-bundle-jsnext-lib');
9644
grunt.loadNpmTasks('grunt-curl');
9745
grunt.loadNpmTasks('grunt-zip');
9846

99-
grunt.registerTask('build', [
100-
'bundle_jsnext', 'uglify', 'cjs_jsnext', 'copy:src', 'concat:complete',
101-
]);
102-
103-
grunt.registerTask('cldr', ['clean:cldr', 'extract-cldr-data', 'compile-data']);
104-
105-
grunt.registerTask('default', ['jshint', 'clean:lib', 'build']);
106-
10747
grunt.registerTask('update-test262', [
10848
'clean:test262',
10949
'curl:test262',

package.json

+11-17
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@
33
"version": "1.1.0",
44
"description": "Polyfill the ECMA-402 Intl API (except collation)",
55
"main": "index.js",
6-
"jsnext:main": "src/main.js",
76
"directories": {
87
"test": "tests"
98
},
@@ -13,8 +12,8 @@
1312
},
1413
"devDependencies": {
1514
"async": "^0.9.0",
16-
1715
"babel-cli": "^6.2.0",
16+
"babel-eslint": "^5.0.0",
1817
"babel-plugin-transform-es2015-modules-commonjs": "^6.4.0",
1918
"babel-plugin-transform-es3-member-expression-literals": "^6.3.13",
2019
"babel-plugin-transform-es3-property-literals": "^6.3.13",
@@ -23,16 +22,6 @@
2322
"babel-preset-es2015": "^6.1.18",
2423
"babel-preset-es2015-rollup": "^1.1.1",
2524
"babel-register": "^6.2.0",
26-
"rimraf": "^2.4.2",
27-
"rollup": "^0.25.0",
28-
"rollup-plugin-babel": "^2.3.9",
29-
"rollup-plugin-commonjs": "^2.2.0",
30-
"rollup-plugin-memory": "^1.0.0",
31-
"rollup-plugin-npm": "^1.3.0",
32-
"rollup-plugin-replace": "^1.1.0",
33-
"rollup-plugin-uglify": "^0.1.0",
34-
35-
"babel-eslint": "^5.0.0",
3625
"cldr-cal-buddhist-full": "28.0.0",
3726
"cldr-cal-chinese-full": "28.0.0",
3827
"cldr-cal-coptic-full": "28.0.0",
@@ -53,17 +42,22 @@
5342
"finalhandler": "^0.4.0",
5443
"glob": "^5.0.3",
5544
"grunt": "^0.4.5",
56-
"grunt-bundle-jsnext-lib": "^0.5.0",
5745
"grunt-cli": "~0.1.13",
5846
"grunt-contrib-clean": "^0.6.0",
59-
"grunt-contrib-concat": "^0.5.0",
6047
"grunt-contrib-copy": "^0.5.0",
61-
"grunt-contrib-jshint": "^0.10.0",
62-
"grunt-contrib-uglify": "^0.5.1",
6348
"grunt-curl": "^2.1.0",
6449
"grunt-zip": "^0.16.2",
6550
"jshint": "^2.5.5",
51+
"mkdirp": "^0.5.1",
6652
"object.assign": "^1.1.1",
53+
"rimraf": "^2.4.2",
54+
"rollup": "^0.25.0",
55+
"rollup-plugin-babel": "^2.3.9",
56+
"rollup-plugin-commonjs": "^2.2.0",
57+
"rollup-plugin-memory": "^1.0.0",
58+
"rollup-plugin-npm": "^1.3.0",
59+
"rollup-plugin-replace": "^1.1.0",
60+
"rollup-plugin-uglify": "^0.1.0",
6761
"sauce-tunnel": "^2.2.3",
6862
"serve-static": "^1.10.0",
6963
"wd": "^0.3.6"
@@ -75,7 +69,7 @@
7569
"build:dist:dev": "NODE_ENV=development babel-node scripts/build-dist",
7670
"build:dist:prod": "NODE_ENV=production babel-node scripts/build-dist",
7771
"build:dist": "npm run build:dist:dev && npm run build:dist:prod",
78-
"build": "npm run build:lib && npm run build:dist",
72+
"build": "npm run build:data && npm run build:lib && npm run build:dist",
7973
"lint": "eslint .",
8074
"test": "cd tests && node noderunner.js && node saucelabs.js",
8175
"pretest": "npm run lint",

scripts/build-data.js

+167
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,167 @@
1+
/* global Promise */
2+
import * as fs from 'fs';
3+
import * as p from 'path';
4+
import {sync as mkdirpSync} from 'mkdirp';
5+
6+
function writeFile(filename, contents) {
7+
return new Promise((resolve, reject) => {
8+
fs.writeFile(filename, contents, (err) => {
9+
if (err) {
10+
reject(err);
11+
} else {
12+
resolve(p.resolve(filename));
13+
}
14+
});
15+
});
16+
}
17+
18+
function mergeData(...sources) {
19+
return sources.reduce((data, source) => {
20+
Object.keys(source || {}).forEach((locale) => {
21+
data[locale] = Object.assign(data[locale] || {}, source[locale]);
22+
});
23+
24+
return data;
25+
}, {});
26+
}
27+
28+
function reviver (k, v) {
29+
let idx;
30+
31+
if (k === 'locale')
32+
return v;
33+
34+
else if (typeof v === 'string') {
35+
idx = prims.indexOf(v);
36+
valCount++;
37+
38+
if (idx === -1)
39+
idx += prims.push(v);
40+
41+
return '###prims['+ idx +']###';
42+
}
43+
44+
else if (typeof v === 'object' && v !== null) {
45+
const str = JSON.stringify(v);
46+
objCount++;
47+
48+
if (objStrs.hasOwnProperty(str))
49+
return objStrs[str];
50+
51+
// We need to make sure this object is not added to the same
52+
// array as an object it references (and we need to check
53+
// this recursively)
54+
let depth;
55+
let objDepths = [0];
56+
57+
for (let key in v) {
58+
if (typeof v[key] === 'string' && (depth = v[key].match(/^###objs\[(\d+)/)))
59+
objDepths.push(+depth[1] + 1);
60+
}
61+
62+
depth = Math.max.apply(Math, objDepths);
63+
64+
if (!Array.isArray(objs[depth]))
65+
objs[depth] = [];
66+
67+
idx = objs[depth].push(v) - 1;
68+
objStrs[str] = '###objs['+ depth +']['+ idx +']###';
69+
70+
return objStrs[str];
71+
}
72+
73+
return v;
74+
}
75+
76+
// -----------------------------------------------------------------------------
77+
78+
mkdirpSync('locale-data/');
79+
mkdirpSync('locale-data/json/');
80+
mkdirpSync('locale-data/jsonp/');
81+
82+
// extracting data into CLDR
83+
84+
// Regex for converting locale JSON to object grammar, obviously simple and
85+
// incomplete but should be good enough for the CLDR JSON
86+
const jsonpExp = /"(?!default)([\w$][\w\d$]+)":/g;
87+
88+
import reduceLocaleData from './utils/reduce';
89+
90+
import extractCalendars from './utils/extract-calendars';
91+
import extractNumbersFields from './utils/extract-numbers';
92+
import {getAllLocales} from './utils/locales';
93+
94+
// Default to all CLDR locales.
95+
const locales = getAllLocales();
96+
97+
// Each type of data has the structure: `{"<locale>": {"<key>": <value>}}`,
98+
// which is well suited for merging into a single object per locale. This
99+
// performs that deep merge and returns the aggregated result.
100+
let locData = mergeData(
101+
extractCalendars(locales),
102+
extractNumbersFields(locales)
103+
);
104+
105+
let locStringData = {};
106+
107+
Object.keys(locData).forEach((locale) => {
108+
// Ignore en-US-POSIX and root
109+
if (locale.toLowerCase() === 'en-us-posix') {
110+
return;
111+
}
112+
113+
const obj = reduceLocaleData(locale, locData[locale]);
114+
locStringData[locale] = JSON.stringify(obj, null, 4);
115+
const jsonpContent = `IntlPolyfill.__addLocaleData(${JSON.stringify(obj).replace(jsonpExp, '$1:')});`;
116+
writeFile('locale-data/json/' + locale + '.json', locStringData[locale]);
117+
writeFile('locale-data/jsonp/' + locale + '.js', jsonpContent);
118+
});
119+
120+
console.log('Total number of locales is ' + Object.keys(locData).length);
121+
122+
// compiling `locale-date/complete.js`
123+
124+
function replacer($0, type, loc) {
125+
return (type === 'prims' ? 'a' : 'b') + loc;
126+
}
127+
128+
let
129+
objStrs = {},
130+
objs = [],
131+
prims = [],
132+
133+
valCount = 0,
134+
objCount = 0,
135+
136+
fileData = '';
137+
138+
fileData += '(function(addLocaleData){\n';
139+
140+
let locReducedData = {};
141+
Object.keys(locStringData).forEach((k) => {
142+
const c = locStringData[k];
143+
locReducedData[k] = JSON.parse(c, reviver);
144+
});
145+
146+
fileData += `var a=${JSON.stringify(prims)},b=[];`;
147+
objs.forEach((val, idx) => {
148+
const ref = JSON.stringify(val).replace(/"###(objs|prims)(\[[^#]+)###"/g, replacer);
149+
150+
fileData += `b[${idx}]=${ref};`;
151+
});
152+
153+
for (let k in locReducedData) {
154+
fileData += `addLocaleData(${locReducedData[k].replace(/###(objs|prims)(\[[^#]+)###/, replacer)});
155+
`;
156+
}
157+
158+
fileData += `})(IntlPolyfill.__addLocaleData);`;
159+
160+
// writting the complete optimized bundle
161+
writeFile('locale-data/complete.js', fileData);
162+
163+
console.log('Total number of reused strings is ' + prims.length + ' (reduced from ' + valCount + ')');
164+
console.log('Total number of reused objects is ' + Object.keys(objStrs).length + ' (reduced from ' + objCount + ')');
165+
166+
process.on('unhandledRejection', (reason) => {throw reason;});
167+
console.log('Writing locale data files...');

0 commit comments

Comments
 (0)