|
1 | 1 | 'use strict'; |
2 | 2 |
|
3 | | -const path = require('path'); |
4 | | -const utils = require('./utils'); |
5 | 3 | const Filter = require('broccoli-persistent-filter'); |
6 | | -const crypto = require('crypto'); |
7 | | -const stringify = require('json-stable-stringify'); |
8 | | -const stripBom = require('strip-bom'); |
9 | | - |
10 | | -function rethrowBuildError(error) { |
11 | | - if (!error) { |
12 | | - throw new Error('Unknown Error'); |
13 | | - } |
14 | | - |
15 | | - if (typeof error === 'string') { |
16 | | - throw new Error('[string exception]: ' + error); |
17 | | - } else { |
18 | | - // augment with location and type information and re-throw. |
19 | | - error.type = 'Template Compiler Error'; |
20 | | - error.location = error.location && error.location.start; |
21 | | - |
22 | | - throw error; |
23 | | - } |
24 | | -} |
| 4 | +const jsStringEscape = require('js-string-escape'); |
25 | 5 |
|
26 | 6 | class TemplateCompiler extends Filter { |
27 | | - constructor(inputTree, _options, requiresModuleApiPolyfill = true) { |
28 | | - let options = _options || {}; |
29 | | - |
| 7 | + constructor(inputTree, options = {}) { |
30 | 8 | if (!('persist' in options)) { |
31 | 9 | options.persist = true; |
32 | 10 | } |
33 | | - |
34 | 11 | super(inputTree, options); |
35 | | - |
36 | | - this.options = options; |
37 | | - this.inputTree = inputTree; |
38 | | - this.requiresModuleApiPolyfill = requiresModuleApiPolyfill; |
39 | | - |
40 | | - // TODO: do we need this? |
41 | | - this.precompile = this.options.templateCompiler.precompile; |
42 | | - |
43 | | - let { templateCompiler, EmberENV } = options; |
44 | | - |
45 | | - utils.initializeEmberENV(templateCompiler, EmberENV); |
46 | 12 | } |
47 | 13 |
|
48 | 14 | baseDir() { |
49 | 15 | return __dirname; |
50 | 16 | } |
51 | 17 |
|
52 | 18 | processString(string, relativePath) { |
53 | | - let srcDir = this.inputPaths[0]; |
54 | | - let srcName = path.join(srcDir, relativePath); |
55 | | - |
56 | | - try { |
57 | | - // we have to reverse these for reasons that are a bit bonkers. the initial |
58 | | - // version of this system used `registeredPlugin` from |
59 | | - // `ember-template-compiler.js` to set up these plugins (because Ember ~ 1.13 |
60 | | - // only had `registerPlugin`, and there was no way to pass plugins directly |
61 | | - // to the call to `compile`/`precompile`). calling `registerPlugin` |
62 | | - // unfortunately **inverted** the order of plugins (it essentially did |
63 | | - // `PLUGINS = [plugin, ...PLUGINS]`). |
64 | | - // |
65 | | - // sooooooo...... we are forced to maintain that **absolutely bonkers** ordering |
66 | | - let astPlugins = this.options.plugins ? [...this.options.plugins.ast].reverse() : []; |
67 | | - |
68 | | - let precompiled = this.options.templateCompiler.precompile(stripBom(string), { |
69 | | - contents: string, |
70 | | - isProduction: this.options.isProduction, |
71 | | - moduleName: relativePath, |
72 | | - parseOptions: { |
73 | | - srcName: srcName, |
74 | | - }, |
75 | | - |
76 | | - // intentionally not using `plugins: this.options.plugins` here |
77 | | - // because if we do, Ember will mutate the shared plugins object (adding |
78 | | - // all of the built in AST transforms into plugins.ast, which breaks |
79 | | - // persistent caching) |
80 | | - plugins: { |
81 | | - ast: astPlugins, |
82 | | - }, |
83 | | - }); |
84 | | - |
85 | | - if (this.options.dependencyInvalidation) { |
86 | | - let plugins = pluginsWithDependencies(this.options.plugins.ast); |
87 | | - let dependencies = []; |
88 | | - for (let i = 0; i < plugins.length; i++) { |
89 | | - let pluginDeps = plugins[i].getDependencies(relativePath); |
90 | | - dependencies = dependencies.concat(pluginDeps); |
91 | | - } |
92 | | - this.dependencies.setDependencies(relativePath, dependencies); |
93 | | - } |
94 | | - |
95 | | - if (this.requiresModuleApiPolyfill) { |
96 | | - return `export default Ember.HTMLBars.template(${precompiled});`; |
97 | | - } else { |
98 | | - return `import { createTemplateFactory } from '@ember/template-factory';\n\nexport default createTemplateFactory(${precompiled});`; |
99 | | - } |
100 | | - } catch (error) { |
101 | | - rethrowBuildError(error); |
| 19 | + return [ |
| 20 | + `import { hbs } from 'ember-cli-htmlbars';`, |
| 21 | + `export default hbs('${jsStringEscape(string)}', { moduleName: '${jsStringEscape( |
| 22 | + relativePath |
| 23 | + )}' });`, |
| 24 | + '', |
| 25 | + ].join('\n'); |
| 26 | + } |
| 27 | + |
| 28 | + getDestFilePath(relativePath) { |
| 29 | + if (relativePath.endsWith('.hbs')) { |
| 30 | + return relativePath.replace(/\.hbs$/, '.js'); |
102 | 31 | } |
103 | 32 | } |
104 | | - |
105 | | - _buildOptionsForHash() { |
106 | | - let strippedOptions = {}; |
107 | | - |
108 | | - for (let key in this.options) { |
109 | | - if (key !== 'templateCompiler') { |
110 | | - strippedOptions[key] = this.options[key]; |
111 | | - } |
112 | | - } |
113 | | - |
114 | | - strippedOptions._requiresModuleApiPolyfill = this.requiresModuleApiPolyfill; |
115 | | - |
116 | | - return strippedOptions; |
117 | | - } |
118 | | - |
119 | | - optionsHash() { |
120 | | - if (!this._optionsHash) { |
121 | | - let templateCompilerCacheKey = utils.getTemplateCompilerCacheKey( |
122 | | - this.options.templateCompilerPath |
123 | | - ); |
124 | | - |
125 | | - this._optionsHash = crypto |
126 | | - .createHash('md5') |
127 | | - .update(stringify(this._buildOptionsForHash()), 'utf8') |
128 | | - .update(templateCompilerCacheKey, 'utf8') |
129 | | - .digest('hex'); |
130 | | - } |
131 | | - |
132 | | - return this._optionsHash; |
133 | | - } |
134 | | - |
135 | | - cacheKeyProcessString(string, relativePath) { |
136 | | - return ( |
137 | | - this.optionsHash() + Filter.prototype.cacheKeyProcessString.call(this, string, relativePath) |
138 | | - ); |
139 | | - } |
140 | 33 | } |
141 | 34 |
|
142 | 35 | TemplateCompiler.prototype.extensions = ['hbs', 'handlebars']; |
143 | 36 | TemplateCompiler.prototype.targetExtension = 'js'; |
144 | 37 |
|
145 | | -function pluginsWithDependencies(registeredPlugins) { |
146 | | - let found = []; |
147 | | - for (let i = 0; i < registeredPlugins.length; i++) { |
148 | | - if (registeredPlugins[i].getDependencies) { |
149 | | - found.push(registeredPlugins[i]); |
150 | | - } |
151 | | - } |
152 | | - return found; |
153 | | -} |
154 | | - |
155 | 38 | module.exports = TemplateCompiler; |
0 commit comments