UNPKG

6.54 kBJavaScriptView Raw
1"use strict";
2/**
3 * @license
4 * Copyright (c) 2016 The Polymer Project Authors. All rights reserved.
5 * This code may only be used under the BSD style license found at
6 * http://polymer.github.io/LICENSE.txt
7 * The complete set of authors may be found at
8 * http://polymer.github.io/AUTHORS.txt
9 * The complete set of contributors may be found at
10 * http://polymer.github.io/CONTRIBUTORS.txt
11 * Code distributed by Google as part of the polymer project is also
12 * subject to an additional IP rights grant found at
13 * http://polymer.github.io/PATENTS.txt
14 */
15Object.defineProperty(exports, "__esModule", { value: true });
16const browser_capabilities_1 = require("browser-capabilities");
17const content_type_1 = require("content-type");
18const fs = require("fs");
19const LRU = require("lru-cache");
20const path = require("path");
21const polymer_build_1 = require("polymer-build");
22const get_compile_target_1 = require("./get-compile-target");
23const transform_middleware_1 = require("./transform-middleware");
24const javaScriptMimeTypes = [
25 'application/javascript',
26 'application/ecmascript',
27 'text/javascript',
28 'text/ecmascript',
29];
30const htmlMimeType = 'text/html';
31const compileMimeTypes = [htmlMimeType, ...javaScriptMimeTypes];
32// Match the polyfills from https://github.com/webcomponents/webcomponentsjs,
33// but not their tests.
34exports.isPolyfill = /(^|\/)webcomponentsjs\/[^\/]+$/;
35function getContentType(response) {
36 const contentTypeHeader = response.get('Content-Type');
37 return contentTypeHeader && content_type_1.parse(contentTypeHeader).type;
38}
39// NOTE: To change the max length of the cache at runtime, just use bracket
40// notation, i.e. `babelCompileCache['max'] = 64 * 1024` for 64KB limit.
41exports.babelCompileCache = LRU({
42 length: (n, key) => n.length + key.length
43});
44// TODO(justinfagnani): see if we can just use the request path as the key
45// See https://github.com/Polymer/polyserve/issues/248
46exports.getCompileCacheKey = (requestPath, body, options) => JSON.stringify(options) + requestPath + body;
47function babelCompile(compile, moduleResolution, rootDir, packageName, componentUrl, componentDir) {
48 return transform_middleware_1.transformResponse({
49 shouldTransform(request, response) {
50 // We must never compile the Custom Elements ES5 Adapter or other
51 // polyfills/shims.
52 if (exports.isPolyfill.test(request.url)) {
53 return false;
54 }
55 if ('nocompile' in request.query) {
56 return false;
57 }
58 if (!compileMimeTypes.includes(getContentType(response))) {
59 return false;
60 }
61 if (compile === 'always' || moduleResolution === 'node') {
62 return true;
63 }
64 if (compile === 'never') {
65 return false;
66 }
67 const capabilities = browser_capabilities_1.browserCapabilities(request.get('user-agent'));
68 return !capabilities.has('es2015') || !capabilities.has('modules');
69 },
70 transform(request, response, body) {
71 const capabilities = browser_capabilities_1.browserCapabilities(request.get('user-agent'));
72 const compileTarget = get_compile_target_1.getCompileTarget(capabilities, compile);
73 const options = {
74 compileTarget,
75 transformModules: compile === 'always' || !capabilities.has('modules'),
76 };
77 const cacheKey = exports.getCompileCacheKey(request.baseUrl + request.path, body, options);
78 const cached = exports.babelCompileCache.get(cacheKey);
79 if (cached !== undefined) {
80 return cached;
81 }
82 // Make sure that componentDir is absolute, like jsTransform expects
83 componentDir = path.resolve(rootDir, componentDir);
84 let transformed;
85 const contentType = getContentType(response);
86 let requestPath = request.path;
87 // TODO(justinfagnani): Use path-is-inside, but test on Windows
88 const isRootPathRequest = request.path === `/${packageName}` ||
89 request.path.startsWith(`/${packageName}/`);
90 const isComponentRequest = request.baseUrl === `/${componentUrl}`;
91 let filePath;
92 if (isRootPathRequest) {
93 requestPath = requestPath.substring(`/${packageName}`.length);
94 }
95 if (isComponentRequest && !isRootPathRequest) {
96 filePath = path.join(componentDir, requestPath);
97 }
98 else {
99 filePath = path.join(rootDir, requestPath);
100 }
101 // The file path needs to include the filename for correct relative
102 // path calculation
103 try {
104 const stat = fs.statSync(filePath);
105 if (stat.isDirectory()) {
106 filePath = path.join(filePath, 'index.html');
107 }
108 }
109 catch (e) {
110 // file not found, will 404 later
111 }
112 if (contentType === htmlMimeType) {
113 transformed = polymer_build_1.htmlTransform(body, {
114 js: {
115 compile: options.compileTarget,
116 moduleResolution,
117 filePath,
118 packageName,
119 isComponentRequest,
120 componentDir,
121 rootDir,
122 transformModulesToAmd: options.transformModules,
123 softSyntaxError: true,
124 },
125 injectAmdLoader: options.transformModules,
126 });
127 }
128 else if (javaScriptMimeTypes.includes(contentType)) {
129 transformed = polymer_build_1.jsTransform(body, {
130 compile: options.compileTarget,
131 transformModulesToAmd: options.transformModules ? 'auto' : false,
132 moduleResolution,
133 filePath: filePath,
134 isComponentRequest,
135 packageName,
136 componentDir,
137 rootDir,
138 });
139 }
140 else {
141 transformed = body;
142 }
143 exports.babelCompileCache.set(cacheKey, transformed);
144 return transformed;
145 },
146 });
147}
148exports.babelCompile = babelCompile;
149//# sourceMappingURL=compile-middleware.js.map
\No newline at end of file