Skip to content

Commit fe86f86

Browse files
Merge branch 'master' of github.com:ampproject/rollup-plugin-closure-compiler
2 parents 0445ebd + 5eed6be commit fe86f86

39 files changed

+6745
-3953
lines changed

.travis.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ node_js:
55
- "lts/*"
66
before_install:
77
- unset _JAVA_OPTIONS # JVM heap sizes break closure compiler. #11203.
8-
script: yarn test
8+
script: npm run test
99
branches:
1010
only:
1111
- master

package-lock.json

Lines changed: 5676 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 8 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -9,16 +9,15 @@
99
},
1010
"author": "The AMP HTML Authors",
1111
"engines": {
12-
"yarn": ">=1",
1312
"node": ">=8"
1413
},
1514
"keywords": [
1615
"rollup-plugin"
1716
],
1817
"license": "Apache-2.0",
1918
"scripts": {
20-
"pretest": "yarn build",
21-
"test": "ava test/*.js",
19+
"pretest": "npm run build",
20+
"test": "ava test/**/*.js",
2221
"build": "rimraf dist && tsc -p tsconfig.json",
2322
"lint": "tslint -c tslint.json -p tsconfig.json"
2423
},
@@ -27,28 +26,28 @@
2726
"temp-write": "^3.4.0"
2827
},
2928
"devDependencies": {
29+
"@types/estree": "^0.0.39",
3030
"@types/google-closure-compiler": "^0.0.18",
3131
"@types/temp-write": "^3.3.0",
32-
"ava": "^0.25.0",
33-
"husky": "1.0.0-rc.9",
32+
"ava": "1.0.0-beta.6",
33+
"husky": "1.0.0-rc.13",
3434
"lint-staged": "^7.2.0",
3535
"prettier": "^1.13.5",
3636
"rimraf": "^2.6.2",
3737
"rollup": "^0.62.0",
38-
"sourcemap-validator": "^1.1.0",
39-
"tslint": "5.10.0",
38+
"tslint": "^5.10.0",
4039
"typescript": "^2.9.2"
4140
},
4241
"lint-staged": {
4342
"*.ts": [
44-
"yarn lint --fix",
43+
"npm run lint --fix",
4544
"prettier --config .prettierrc --write",
4645
"git add"
4746
]
4847
},
4948
"husky": {
5049
"hooks": {
51-
"pre-push": "yarn test",
50+
"pre-push": "npm run test",
5251
"pre-commit": "lint-staged"
5352
}
5453
}

src/compiler.ts

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
/**
2+
* Copyright 2018 The AMP HTML Authors. All Rights Reserved.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS-IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
import { compiler, CompileOptions } from 'google-closure-compiler';
18+
import { Transform } from './types';
19+
import { postCompilation } from './transforms';
20+
21+
/**
22+
* Run Closure Compiler and `postCompilation` Transforms on input source.
23+
* @param compileOptions Closure Compiler CompileOptions, normally derived from Rollup configuration
24+
* @param transforms Transforms to run rollowing compilation
25+
* @return Promise<string> source following compilation and Transforms.
26+
*/
27+
export default function(
28+
compileOptions: CompileOptions,
29+
transforms: Array<Transform>,
30+
): Promise<string> {
31+
return new Promise((resolve: (stdOut: string) => void, reject: (error: any) => void) => {
32+
new compiler(compileOptions).run(async (exitCode: number, code: string, stdErr: string) => {
33+
if (exitCode !== 0) {
34+
reject(new Error(`Google Closure Compiler exit ${exitCode}: ${stdErr}`));
35+
} else {
36+
resolve(await postCompilation(code, transforms));
37+
}
38+
});
39+
});
40+
}

src/index.ts

Lines changed: 45 additions & 62 deletions
Original file line numberDiff line numberDiff line change
@@ -14,76 +14,59 @@
1414
* limitations under the License.
1515
*/
1616

17-
import { compiler, CompileOptions } from 'google-closure-compiler';
18-
import { sync } from 'temp-write';
19-
import { readFileSync } from 'fs';
20-
import { OutputOptions, RawSourceMap, Plugin } from 'rollup';
17+
import { CompileOptions } from 'google-closure-compiler';
18+
import * as fs from 'fs';
19+
import { promisify } from 'util';
20+
import { OutputOptions, RawSourceMap, Plugin, OutputChunk } from 'rollup';
21+
import compiler from './compiler';
22+
import options from './options';
23+
import { preCompilation, createTransforms, deriveFromInputSource } from './transforms';
24+
import { Transform } from './types';
2125

22-
export const defaultCompileOptions = (outputOptions: OutputOptions): CompileOptions => {
23-
// Defaults for Rollup Projects are slightly different than Closure Compiler defaults.
24-
// - Users of Rollup tend to transpile their code before handing it to a minifier,
25-
// so no transpile is default.
26-
// - When Rollup output is set to "es" it is expected the code will live in a ES Module,
27-
// so safely be more aggressive in minification.
28-
// - When Rollup is configured to output an iife, ensure Closure Compiler does not
29-
// mangle the name of the iife wrapper.
26+
const readFile = promisify(fs.readFile);
3027

31-
let externs: string = `
3228
/**
33-
* @fileoverview Externs built via derived configuration from Rollup or input code.
34-
* @externs
35-
*/`;
36-
37-
const options: CompileOptions = {
38-
language_out: 'NO_TRANSPILE',
39-
assume_function_wrapper: outputOptions.format === 'es' ? true : false,
40-
warning_level: 'QUIET',
41-
};
42-
if (outputOptions.format === 'iife' && outputOptions.name) {
43-
externs = `${externs}\nvar ${outputOptions.name} = function(){};`;
44-
45-
options['externs'] = sync(externs);
46-
}
29+
* Transform the tree-shaken code from Rollup with Closure Compiler (with derived configuration and transforms)
30+
* @param compileOptions Closure Compiler compilation options from Rollup configuration.
31+
* @param transforms Transforms to apply to source followin Closure Compiler completion.
32+
* @param code Source to compile.
33+
* @param outputOptions Rollup Output Options.
34+
* @return Closure Compiled form of the Rollup Chunk
35+
*/
36+
export const transformChunk = async (
37+
transforms: Array<Transform>,
38+
requestedCompileOptions: CompileOptions,
39+
sourceCode: string,
40+
outputOptions: OutputOptions,
41+
): Promise<{ code: string; map: RawSourceMap } | void> => {
42+
const code = await preCompilation(sourceCode, outputOptions, transforms);
43+
const [compileOptions, mapFile] = options(
44+
requestedCompileOptions,
45+
outputOptions,
46+
code,
47+
transforms,
48+
);
4749

48-
return options;
50+
return compiler(compileOptions, transforms).then(
51+
async code => {
52+
return { code, map: JSON.parse(await readFile(mapFile, 'utf8')) };
53+
},
54+
(error: Error) => {
55+
throw error;
56+
},
57+
);
4958
};
5059

51-
export default function closureCompiler(compileOptions: CompileOptions = {}): Plugin {
60+
export default function closureCompiler(requestedCompileOptions: CompileOptions = {}): Plugin {
61+
let transforms: Array<Transform>;
62+
5263
return {
5364
name: 'closure-compiler',
54-
transformBundle: (
55-
code: string,
56-
outputOptions: OutputOptions,
57-
): Promise<{ code: string; map: RawSourceMap } | void> => {
58-
const temp = {
59-
js: sync(code),
60-
map: sync(''),
61-
};
62-
63-
compileOptions = Object.assign(defaultCompileOptions(outputOptions), compileOptions, {
64-
js: temp.js,
65-
create_source_map: temp.map,
66-
});
67-
68-
const compile: Promise<string> = new Promise((resolve, reject) => {
69-
new compiler(compileOptions).run((exitCode: number, stdOut: string, stdErr: string) => {
70-
if (exitCode !== 0) {
71-
reject(new Error(`Google Closure Compiler exit ${exitCode}: ${stdErr}`));
72-
} else {
73-
resolve(stdOut);
74-
}
75-
});
76-
});
77-
78-
return compile.then(
79-
stdOut => {
80-
const sourceMap: RawSourceMap = JSON.parse(readFileSync(temp.map, 'utf8'));
81-
return { code: stdOut, map: sourceMap };
82-
},
83-
(error: Error) => {
84-
throw error;
85-
},
86-
);
65+
load() {
66+
transforms = transforms || createTransforms(this);
8767
},
68+
transform: async (code: string) => deriveFromInputSource(code, transforms),
69+
transformChunk: async (code: string, outputOptions: OutputOptions, chunk: OutputChunk) =>
70+
await transformChunk(transforms, requestedCompileOptions, code, outputOptions),
8871
};
8972
}

src/options.ts

Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
/**
2+
* Copyright 2018 The AMP HTML Authors. All Rights Reserved.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS-IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
import { Transform } from './types';
18+
import { OutputOptions } from 'rollup';
19+
import { CompileOptions } from 'google-closure-compiler';
20+
import { sync } from 'temp-write';
21+
22+
/**
23+
* Generate default Closure Compiler CompileOptions an author can override if they wish.
24+
* These must be derived from configuration or input sources.
25+
* @param transformers
26+
* @param options
27+
* @return derived CompileOptions for Closure Compiler
28+
*/
29+
export const defaults = (
30+
options: OutputOptions,
31+
transformers: Array<Transform> | null,
32+
): CompileOptions => {
33+
// Defaults for Rollup Projects are slightly different than Closure Compiler defaults.
34+
// - Users of Rollup tend to transpile their code before handing it to a minifier,
35+
// so no transpile is default.
36+
// - When Rollup output is set to "es" it is expected the code will live in a ES Module,
37+
// so safely be more aggressive in minification.
38+
// - When Rollup is configured to output an iife, ensure Closure Compiler does not
39+
// mangle the name of the iife wrapper.
40+
41+
const externs = transformers
42+
? transformers.map(transform => sync(transform.extern(options)))
43+
: '';
44+
45+
return {
46+
language_out: 'NO_TRANSPILE',
47+
assume_function_wrapper: options.format === 'es' ? true : false,
48+
warning_level: 'QUIET',
49+
externs,
50+
};
51+
};
52+
53+
/**
54+
* Compile Options is the final configuration to pass into Closure Compiler.
55+
* defaultCompileOptions are overrideable by ones passed in directly to the plugin
56+
* but the js source and sourcemap are not overrideable, since this would break the output if passed.
57+
* @param compileOptions
58+
* @param outputOptions
59+
* @param code
60+
* @param transforms
61+
*/
62+
export default function(
63+
compileOptions: CompileOptions,
64+
outputOptions: OutputOptions,
65+
code: string,
66+
transforms: Array<Transform> | null,
67+
): [CompileOptions, string] {
68+
const mapFile = sync('');
69+
70+
return [
71+
{
72+
...defaults(outputOptions, transforms),
73+
...compileOptions,
74+
js: sync(code),
75+
create_source_map: mapFile,
76+
},
77+
mapFile,
78+
];
79+
}

0 commit comments

Comments
 (0)