From 5671ce5e30e815ef1b41b2503c2ba153129ba0a6 Mon Sep 17 00:00:00 2001 From: Matthew Edwards Date: Fri, 29 Apr 2022 13:14:02 -0700 Subject: [PATCH 1/9] Add babel plugin for preprocessing templates with ast transforms --- packages/addon-dev/.gitignore | 3 + packages/addon-dev/jest.config.js | 6 + packages/addon-dev/package.json | 12 +- .../src/template-transform-plugin.ts | 81 ++++++++++ .../tests/template-transform-plugin.test.ts | 139 ++++++++++++++++++ 5 files changed, 240 insertions(+), 1 deletion(-) create mode 100644 packages/addon-dev/jest.config.js create mode 100644 packages/addon-dev/src/template-transform-plugin.ts create mode 100644 packages/addon-dev/tests/template-transform-plugin.test.ts diff --git a/packages/addon-dev/.gitignore b/packages/addon-dev/.gitignore index 2ebf498ab..9b6211a0a 100644 --- a/packages/addon-dev/.gitignore +++ b/packages/addon-dev/.gitignore @@ -4,6 +4,9 @@ /src/**/*.js /src/**/*.d.ts /src/**/*.map +/tests/**/*.js +/tests/**/*.d.ts +/tests/**/*.map # dependencies /node_modules/ diff --git a/packages/addon-dev/jest.config.js b/packages/addon-dev/jest.config.js new file mode 100644 index 000000000..7f4f45dca --- /dev/null +++ b/packages/addon-dev/jest.config.js @@ -0,0 +1,6 @@ +module.exports = { + testEnvironment: 'node', + testMatch: [ + '/tests/**/*.test.js', + ], +}; diff --git a/packages/addon-dev/package.json b/packages/addon-dev/package.json index 6a94fd0e8..325926a56 100644 --- a/packages/addon-dev/package.json +++ b/packages/addon-dev/package.json @@ -14,6 +14,7 @@ }, "exports": { "./template-colocation-plugin": "./src/template-colocation-plugin.js", + "./template-transform-plugin": "./src/template-transform-plugin.js", "./rollup": "./src/rollup.js" }, "files": [ @@ -22,6 +23,10 @@ "src/**/*.d.ts", "src/**/*.js.map" ], + "scripts": { + "prepare": "tsc", + "test": "jest" + }, "dependencies": { "@embroider/shared-internals": "^1.7.1", "@rollup/pluginutils": "^4.1.1", @@ -34,10 +39,15 @@ "yargs": "^17.0.1" }, "devDependencies": { + "@embroider/test-support": "0.36.0", "@types/fs-extra": "^9.0.12", "@types/minimatch": "^3.0.4", "@types/yargs": "^17.0.3", - "rollup": "^2.58.0" + "rollup": "^2.58.0", + "tmp": "^0.1.0" + }, + "peerDependencies": { + "@glimmer/syntax": "*" }, "engines": { "node": "12.* || 14.* || >= 16" diff --git a/packages/addon-dev/src/template-transform-plugin.ts b/packages/addon-dev/src/template-transform-plugin.ts new file mode 100644 index 000000000..3d6da63ed --- /dev/null +++ b/packages/addon-dev/src/template-transform-plugin.ts @@ -0,0 +1,81 @@ +import type * as Babel from '@babel/core'; +import type { types as t } from '@babel/core'; +import type { NodePath } from '@babel/traverse'; +import { preprocess, print } from '@glimmer/syntax'; + +export interface Options { + astTransforms?: Array; +} + +interface State { + opts: Options; + localName: string | undefined; +} + +export default function main(babel: typeof Babel) { + let t = babel.types; + + return { + visitor: { + ImportDeclaration(path: NodePath, state: State) { + if (path.node.source.value !== 'ember-cli-htmlbars') { + return; + } + + const specifier = path.node.specifiers.find( + (s) => + t.isImportSpecifier(s) && + t.isIdentifier(s.imported) && + s.imported.name === 'hbs' + ); + + if (!specifier) { + return; + } + + state.localName = specifier.local.name; + }, + CallExpression(path: NodePath, state: State) { + const localName = state.localName; + + if (!t.isIdentifier(path.node.callee)) { + return; + } + + const callee = path.node.callee; + + if (!localName || callee.name !== localName) { + return; + } + + let template = (path.node.arguments[0] as t.StringLiteral).value; + + let options = { + astTransforms: [], + ...state.opts, + }; + + const astTransforms = options.astTransforms.map((maybeFunc) => { + return typeof maybeFunc === 'string' + ? require(maybeFunc) // If it's a string attempt to resolve the path to a module. + : maybeFunc; + }); + + if (astTransforms.length < 1) { + return; + } + + const ast = preprocess(template, { + plugins: { + ast: [...astTransforms], + }, + }); + + const augmentedTemplate = print(ast); + + // Create a new stringLiteral with the augmentedTemplate + path.node.arguments[0] = t.stringLiteral(augmentedTemplate); + }, + }, + }; +} diff --git a/packages/addon-dev/tests/template-transform-plugin.test.ts b/packages/addon-dev/tests/template-transform-plugin.test.ts new file mode 100644 index 000000000..24512011a --- /dev/null +++ b/packages/addon-dev/tests/template-transform-plugin.test.ts @@ -0,0 +1,139 @@ +import { allBabelVersions } from '@embroider/test-support'; +import { Options } from '../src/template-transform-plugin'; +import { hbsToJS } from '@embroider/shared-internals'; +import { AST } from '@glimmer/syntax'; +import { join } from 'path'; +import tmp from 'tmp'; +import { writeFileSync } from 'fs-extra'; + +describe('template-transform-plugin', () => { + jest.setTimeout(120000); + + const templateTransformBabelPlugin = join( + __dirname, + '../src/template-transform-plugin.js' + ); + + let plugins: any = []; + + function reverseTransform() { + return { + name: 'reverse-transform', + visitor: { + ElementNode(node: AST.ElementNode) { + node.tag = node.tag.split('').reverse().join(''); + }, + }, + }; + } + + function setupPlugins(options?: Options) { + plugins = [[templateTransformBabelPlugin, options]]; + } + + allBabelVersions({ + babelConfig() { + return { + plugins, + }; + }, + createTests(transform) { + afterEach(function () { + plugins = undefined; + // options = undefined; + }); + + test('no-op', () => { + setupPlugins(); + const code = hbsToJS('Hello {{@phrase}}'); + let output = transform(code); + expect(output).toMatch( + /import { hbs } from ['"]ember-cli-htmlbars['"];/ + ); + expect(output).toMatch( + /export default hbs\(['"]Hello {{@phrase}}['"]\);/ + ); + }); + + test('options.astTransforms empty array', () => { + setupPlugins({ + astTransforms: [], + }); + const code = hbsToJS('Hello {{@phrase}}'); + let output = transform(code); + expect(output).toMatch( + /import { hbs } from ['"]ember-cli-htmlbars['"];/ + ); + expect(output).toMatch( + /export default hbs\(['"]Hello {{@phrase}}['"]\);/ + ); + }); + test('options.astTransforms function', () => { + setupPlugins({ + astTransforms: [reverseTransform], + }); + + const code = hbsToJS('{{@phrase}}'); + let output = transform(code); + expect(output).toMatch( + /import { hbs } from ['"]ember-cli-htmlbars['"];/ + ); + expect(output).toMatch( + /export default hbs\(['"]\{{@phrase}}\<\/naps\>['"]\);/ + ); + }); + + test('options.astTransforms path', () => { + const someFile = tmp.fileSync(); + + const contents = `module.exports = function reverseTransform() { + return { + name: 'reverse-transform', + visitor: { + ElementNode(node) { + node.tag = node.tag.split('').reverse().join(''); + }, + }, + }; +}`; + + writeFileSync(someFile.name, contents, 'utf8'); + + setupPlugins({ + astTransforms: [someFile.name], + }); + + const code = hbsToJS('{{@phrase}}'); + + let output = transform(code); + + expect(output).toMatch( + /import { hbs } from ['"]ember-cli-htmlbars['"];/ + ); + expect(output).toMatch( + /export default hbs\(['"]\{{@phrase}}\<\/naps\>['"]\);/ + ); + + someFile.removeCallback(); + }); + + test('ember-cli-htmlbars alias import name', () => { + setupPlugins({ + astTransforms: [reverseTransform], + }); + + const code = `import { hbs as render } from 'ember-cli-htmlbars'; +export default render('{{@phrase}}');`; + + let output = transform(code); + + expect(output).toMatch( + /import { hbs as render } from ['"]ember-cli-htmlbars['"];/ + ); + expect(output).toMatch( + /export default render\(['"]\{{@phrase}}\<\/naps\>['"]\);/ + ); + }); + }, + }); +}); From f8ba147163097259b42719b307254d40acb4315e Mon Sep 17 00:00:00 2001 From: Matthew Edwards Date: Mon, 2 May 2022 13:22:20 -0700 Subject: [PATCH 2/9] Disable linting on require(...) line in babel plugin --- packages/addon-dev/src/template-transform-plugin.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/packages/addon-dev/src/template-transform-plugin.ts b/packages/addon-dev/src/template-transform-plugin.ts index 3d6da63ed..3661f0bcb 100644 --- a/packages/addon-dev/src/template-transform-plugin.ts +++ b/packages/addon-dev/src/template-transform-plugin.ts @@ -56,8 +56,9 @@ export default function main(babel: typeof Babel) { }; const astTransforms = options.astTransforms.map((maybeFunc) => { + // If it's a string attempt to resolve the path to a module. return typeof maybeFunc === 'string' - ? require(maybeFunc) // If it's a string attempt to resolve the path to a module. + ? require(maybeFunc) // eslint-disable-line @typescript-eslint/no-require-imports : maybeFunc; }); From 26172c0684b0b1aacb6ae969e2b937ac71d397eb Mon Sep 17 00:00:00 2001 From: Matthew Edwards Date: Thu, 26 May 2022 11:32:20 -0700 Subject: [PATCH 3/9] Expose template-colocation-plugin in core; addon-dev now depends on core --- packages/addon-dev/package.json | 2 +- packages/addon-dev/src/rollup-addon-dependencies.ts | 2 +- packages/addon-dev/src/template-colocation-plugin.ts | 11 +++++++---- packages/shared-internals/src/index.ts | 4 ++++ 4 files changed, 13 insertions(+), 6 deletions(-) diff --git a/packages/addon-dev/package.json b/packages/addon-dev/package.json index 325926a56..71ec52b70 100644 --- a/packages/addon-dev/package.json +++ b/packages/addon-dev/package.json @@ -28,7 +28,7 @@ "test": "jest" }, "dependencies": { - "@embroider/shared-internals": "^1.7.1", + "@embroider/core": "^1.7.1", "@rollup/pluginutils": "^4.1.1", "assert-never": "^1.2.1", "fs-extra": "^10.0.0", diff --git a/packages/addon-dev/src/rollup-addon-dependencies.ts b/packages/addon-dev/src/rollup-addon-dependencies.ts index d7bfa5468..0f0172fdc 100644 --- a/packages/addon-dev/src/rollup-addon-dependencies.ts +++ b/packages/addon-dev/src/rollup-addon-dependencies.ts @@ -5,7 +5,7 @@ import { emberVirtualPeerDeps, packageName, templateCompilationModules, -} from '@embroider/shared-internals'; +} from '@embroider/core'; const compilationModules = new Set( templateCompilationModules.map((m) => m.module) diff --git a/packages/addon-dev/src/template-colocation-plugin.ts b/packages/addon-dev/src/template-colocation-plugin.ts index c8600be26..61c32b466 100644 --- a/packages/addon-dev/src/template-colocation-plugin.ts +++ b/packages/addon-dev/src/template-colocation-plugin.ts @@ -1,4 +1,7 @@ -export { - default, - Options, -} from '@embroider/shared-internals/src/template-colocation-plugin'; +import { + templateColocationPlugin, + Options as TemplateColocationPluginOptions, +} from '@embroider/core'; + +export { TemplateColocationPluginOptions as Options }; +export default templateColocationPlugin; diff --git a/packages/shared-internals/src/index.ts b/packages/shared-internals/src/index.ts index 245264dde..7e135dfc5 100644 --- a/packages/shared-internals/src/index.ts +++ b/packages/shared-internals/src/index.ts @@ -9,3 +9,7 @@ export { default as tmpdir } from './tmpdir'; export * from './ember-cli-models'; export * from './ember-standard-modules'; export { hbsToJS } from './hbs-to-js'; +export { + default as templateColocationPlugin, + Options as TemplateColocationPluginOptions, +} from './template-colocation-plugin'; From 08b58a33017f534a5ff74f426c15f657ede51b1c Mon Sep 17 00:00:00 2001 From: Matthew Edwards Date: Wed, 1 Jun 2022 10:43:42 -0700 Subject: [PATCH 4/9] Add documentation --- PORTING-ADDONS-TO-V2.md | 16 ++++++++-------- packages/addon-dev/sample-babel.config.js | 21 +++++++++++++++++++++ 2 files changed, 29 insertions(+), 8 deletions(-) create mode 100644 packages/addon-dev/sample-babel.config.js diff --git a/PORTING-ADDONS-TO-V2.md b/PORTING-ADDONS-TO-V2.md index 82de5874e..c19239b28 100644 --- a/PORTING-ADDONS-TO-V2.md +++ b/PORTING-ADDONS-TO-V2.md @@ -61,10 +61,7 @@ The steps: ```json { "private": true, - "workspaces": [ - "addon", - "test-app" - ] + "workspaces": ["addon", "test-app"] } ``` @@ -219,6 +216,7 @@ Now that we've separated the test-app and docs app concerns from the addon, we c `yarn add --dev @embroider/addon-dev rollup @rollup/plugin-babel @babel/core @babel/plugin-proposal-class-properties @babel/plugin-proposal-decorators` 6. Grab the [example babel config](https://github.com/embroider-build/embroider/blob/main/packages/addon-dev/sample-babel.config.json) and save it as `addon/babel.config.json` + - If you addon requires template transforms in order to publish to a shareable format. Apply transforms using the `@embroider/addon-dev/template-transform-plugin`. View how to use this in the [example babel.config.js](https://github.com/embroider-build/embroider/blob/main/packages/addon-dev/sample-babel.config.js) 7. Grab the [example rollup config](https://github.com/embroider-build/embroider/blob/main/packages/addon-dev/sample-rollup.config.js) and save it as `addon/rollup.config.js`. 8. Identify your **app reexports**. This is the list of modules from your addon that get reexported by files in the `addon/app` directory. 9. Delete the `addon/app` directory. You aren't going to need it anymore. @@ -230,10 +228,12 @@ Now that we've separated the test-app and docs app concerns from the addon, we c 11. Still editing `addon/rollup.config.js`, customize the `appReexports` to match all your **app reexports** as identified above. 12. Delete your `addon/index.js` file. 13. Create a new `addon/addon-main.js` file (this replaces `addon/index.js`) with this exact content: - ```js - const { addonV1Shim } = require('@embroider/addon-shim'); - module.exports = addonV1Shim(__dirname); - ``` + +```js +const { addonV1Shim } = require('@embroider/addon-shim'); +module.exports = addonV1Shim(__dirname); +``` + 14. In your `addon/.eslintrc.js`, replace "index.js" with "addon-main.js" so that our new file will lint correctly as Node code. 15. In your `addon/package.json`, add these things: ```js diff --git a/packages/addon-dev/sample-babel.config.js b/packages/addon-dev/sample-babel.config.js new file mode 100644 index 000000000..785878947 --- /dev/null +++ b/packages/addon-dev/sample-babel.config.js @@ -0,0 +1,21 @@ +// Some addons need to transform their templates before they have a portable format. +// In "classic" builds this was done by the application.In embroider it should be +// done during the addon build. +const someAstTransformPlugin = require('./some-ast-transform-plugin'); + +module.exports = { + plugins: [ + '@embroider/addon-dev/template-colocation-plugin', + [ + '@embroider/addon-dev/template-transform-plugin', + { + astTransforms: [ + someAstTransformPlugin, + './path/to/another-template-transform-plugin', + ], + }, + ], + ['@babel/plugin-proposal-decorators', { legacy: true }], + '@babel/plugin-proposal-class-properties', + ], +}; From 9b95267538ffb5b5edd9091cec507b43ffe7629e Mon Sep 17 00:00:00 2001 From: Matthew Edwards Date: Wed, 1 Jun 2022 10:44:04 -0700 Subject: [PATCH 5/9] Refactor template-transform-plugin to depend on babel-plugin-stage1-inline-hbs --- .../src/template-transform-plugin.ts | 101 +++++------------- .../tests/template-transform-plugin.test.ts | 44 +++++--- 2 files changed, 56 insertions(+), 89 deletions(-) diff --git a/packages/addon-dev/src/template-transform-plugin.ts b/packages/addon-dev/src/template-transform-plugin.ts index 3661f0bcb..4c5e8c516 100644 --- a/packages/addon-dev/src/template-transform-plugin.ts +++ b/packages/addon-dev/src/template-transform-plugin.ts @@ -1,82 +1,37 @@ -import type * as Babel from '@babel/core'; -import type { types as t } from '@babel/core'; -import type { NodePath } from '@babel/traverse'; -import { preprocess, print } from '@glimmer/syntax'; +import make from '@embroider/core/src/babel-plugin-stage1-inline-hbs'; +import { TemplateCompiler, TemplateCompilerParams } from '@embroider/core'; +import { getEmberExports } from '@embroider/core/src/load-ember-template-compiler'; +import { EmberENV } from '@embroider/core'; +type TemplateTransform = () => { name: string; visitor: {} }; + +export type TemplateTransformPlugin = TemplateTransform | string; export interface Options { - astTransforms?: Array; + astTransforms: TemplateTransformPlugin[] | undefined; + compilerPath: string; + EmberENV: EmberENV; } -interface State { - opts: Options; - localName: string | undefined; +function resolvePlugins(plugins: TemplateTransformPlugin[]) { + return plugins.map((somePlugin: TemplateTransformPlugin) => { + // If it's a string attempt to resolve the path to a module. + return typeof somePlugin === 'string' + ? require(somePlugin) // eslint-disable-line @typescript-eslint/no-require-imports + : somePlugin; + }); } -export default function main(babel: typeof Babel) { - let t = babel.types; - - return { - visitor: { - ImportDeclaration(path: NodePath, state: State) { - if (path.node.source.value !== 'ember-cli-htmlbars') { - return; - } - - const specifier = path.node.specifiers.find( - (s) => - t.isImportSpecifier(s) && - t.isIdentifier(s.imported) && - s.imported.name === 'hbs' - ); - - if (!specifier) { - return; - } - - state.localName = specifier.local.name; - }, - CallExpression(path: NodePath, state: State) { - const localName = state.localName; - - if (!t.isIdentifier(path.node.callee)) { - return; - } - - const callee = path.node.callee; - - if (!localName || callee.name !== localName) { - return; - } +export default make((options: Options) => { + let { compilerPath, astTransforms: somePlugins = [], ...opts } = options; + const astTransforms: TemplateTransform[] = resolvePlugins(somePlugins); - let template = (path.node.arguments[0] as t.StringLiteral).value; - - let options = { - astTransforms: [], - ...state.opts, - }; - - const astTransforms = options.astTransforms.map((maybeFunc) => { - // If it's a string attempt to resolve the path to a module. - return typeof maybeFunc === 'string' - ? require(maybeFunc) // eslint-disable-line @typescript-eslint/no-require-imports - : maybeFunc; - }); - - if (astTransforms.length < 1) { - return; - } - - const ast = preprocess(template, { - plugins: { - ast: [...astTransforms], - }, - }); - - const augmentedTemplate = print(ast); - - // Create a new stringLiteral with the augmentedTemplate - path.node.arguments[0] = t.stringLiteral(augmentedTemplate); - }, + const params: TemplateCompilerParams = { + loadEmberTemplateCompiler: () => getEmberExports(compilerPath), + plugins: { + ast: astTransforms, }, + ...opts, }; -} + + return new TemplateCompiler(params); +}); diff --git a/packages/addon-dev/tests/template-transform-plugin.test.ts b/packages/addon-dev/tests/template-transform-plugin.test.ts index 24512011a..fca1fcdc4 100644 --- a/packages/addon-dev/tests/template-transform-plugin.test.ts +++ b/packages/addon-dev/tests/template-transform-plugin.test.ts @@ -1,6 +1,12 @@ -import { allBabelVersions } from '@embroider/test-support'; -import { Options } from '../src/template-transform-plugin'; -import { hbsToJS } from '@embroider/shared-internals'; +import { + allBabelVersions, + emberTemplateCompilerPath, +} from '@embroider/test-support'; +import { + TemplateTransformPlugin, + Options, +} from '../src/template-transform-plugin'; +import { hbsToJS } from '@embroider/core'; import { AST } from '@glimmer/syntax'; import { join } from 'path'; import tmp from 'tmp'; @@ -27,8 +33,15 @@ describe('template-transform-plugin', () => { }; } - function setupPlugins(options?: Options) { - plugins = [[templateTransformBabelPlugin, options]]; + function setupPlugins(options?: { + astTransforms: TemplateTransformPlugin[]; + }) { + const opts: Options = { + astTransforms: options?.astTransforms, + compilerPath: emberTemplateCompilerPath(), + EmberENV: {}, + }; + plugins = [[templateTransformBabelPlugin, opts]]; } allBabelVersions({ @@ -40,7 +53,6 @@ describe('template-transform-plugin', () => { createTests(transform) { afterEach(function () { plugins = undefined; - // options = undefined; }); test('no-op', () => { @@ -87,15 +99,15 @@ describe('template-transform-plugin', () => { const someFile = tmp.fileSync(); const contents = `module.exports = function reverseTransform() { - return { - name: 'reverse-transform', - visitor: { - ElementNode(node) { - node.tag = node.tag.split('').reverse().join(''); - }, - }, - }; -}`; + return { + name: 'reverse-transform', + visitor: { + ElementNode(node) { + node.tag = node.tag.split('').reverse().join(''); + }, + }, + }; + }`; writeFileSync(someFile.name, contents, 'utf8'); @@ -123,7 +135,7 @@ describe('template-transform-plugin', () => { }); const code = `import { hbs as render } from 'ember-cli-htmlbars'; -export default render('{{@phrase}}');`; + export default render('{{@phrase}}');`; let output = transform(code); From a4f70a0c0b3ac53e2ed8987782617fecac566da4 Mon Sep 17 00:00:00 2001 From: Matthew Edwards Date: Wed, 1 Jun 2022 11:26:13 -0700 Subject: [PATCH 6/9] compilerPath and expose stage1 plugin from core --- packages/addon-dev/sample-babel.config.js | 3 +++ packages/core/package.json | 1 + 2 files changed, 4 insertions(+) diff --git a/packages/addon-dev/sample-babel.config.js b/packages/addon-dev/sample-babel.config.js index 785878947..c9ed7226d 100644 --- a/packages/addon-dev/sample-babel.config.js +++ b/packages/addon-dev/sample-babel.config.js @@ -13,6 +13,9 @@ module.exports = { someAstTransformPlugin, './path/to/another-template-transform-plugin', ], + compilerPath: require.resolve( + 'ember-source/dist/ember-template-compiler' + ), }, ], ['@babel/plugin-proposal-decorators', { legacy: true }], diff --git a/packages/core/package.json b/packages/core/package.json index 45fa1c1fd..c26419b8a 100644 --- a/packages/core/package.json +++ b/packages/core/package.json @@ -18,6 +18,7 @@ }, "./src/messages": "./src/messages.js", "./src/babel-plugin-inline-hbs": "./src/babel-plugin-inline-hbs.js", + "./src/babel-plugin-stage1-inline-hbs": "./src/babel-plugin-stage1-inline-hbs.js", "./src/mini-modules-polyfill": "./src/mini-modules-polyfill.js", "./src/load-ember-template-compiler": "./src/load-ember-template-compiler.js" }, From 000dfcd6d8a25d59170f6e22d03f4313e6ed20b5 Mon Sep 17 00:00:00 2001 From: Matthew Edwards Date: Wed, 1 Jun 2022 13:31:34 -0700 Subject: [PATCH 7/9] Use embroider/core instead of shared-internals --- packages/addon-dev/src/rollup-hbs-plugin.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/addon-dev/src/rollup-hbs-plugin.ts b/packages/addon-dev/src/rollup-hbs-plugin.ts index d8f180215..16529415c 100644 --- a/packages/addon-dev/src/rollup-hbs-plugin.ts +++ b/packages/addon-dev/src/rollup-hbs-plugin.ts @@ -6,7 +6,7 @@ import type { ResolvedId, } from 'rollup'; import { readFileSync } from 'fs'; -import { hbsToJS } from '@embroider/shared-internals'; +import { hbsToJS } from '@embroider/core'; import assertNever from 'assert-never'; import { parse as pathParse } from 'path'; From 09f84815f02c32c709402fe7a487dce03d7fcc4c Mon Sep 17 00:00:00 2001 From: Matthew Edwards Date: Wed, 1 Jun 2022 13:55:48 -0700 Subject: [PATCH 8/9] Refactor API to minimum options; ember-source is a peerDep --- packages/addon-dev/package.json | 3 +- packages/addon-dev/sample-babel.config.js | 11 ++-- .../src/template-transform-plugin.ts | 21 +++++--- .../tests/template-transform-plugin.test.ts | 1 - yarn.lock | 50 +++++++++++++++++-- 5 files changed, 68 insertions(+), 18 deletions(-) diff --git a/packages/addon-dev/package.json b/packages/addon-dev/package.json index 71ec52b70..7c63ae891 100644 --- a/packages/addon-dev/package.json +++ b/packages/addon-dev/package.json @@ -40,6 +40,7 @@ }, "devDependencies": { "@embroider/test-support": "0.36.0", + "@glimmer/syntax": "^0.84.2", "@types/fs-extra": "^9.0.12", "@types/minimatch": "^3.0.4", "@types/yargs": "^17.0.3", @@ -47,7 +48,7 @@ "tmp": "^0.1.0" }, "peerDependencies": { - "@glimmer/syntax": "*" + "ember-source": "*" }, "engines": { "node": "12.* || 14.* || >= 16" diff --git a/packages/addon-dev/sample-babel.config.js b/packages/addon-dev/sample-babel.config.js index c9ed7226d..91a6dc8ee 100644 --- a/packages/addon-dev/sample-babel.config.js +++ b/packages/addon-dev/sample-babel.config.js @@ -1,8 +1,12 @@ // Some addons need to transform their templates before they have a portable format. -// In "classic" builds this was done by the application.In embroider it should be -// done during the addon build. +// In "classic" builds this was done at the application. In embroider it should +// be done during the addon build. const someAstTransformPlugin = require('./some-ast-transform-plugin'); +// The `@embroider/addon-dev/template-transform-plugin` has the following options: +// `options.astTransforms` - an array of functions or paths to preprocess the GlimmerAST +// `options.compilerPath` - Optional: Defaults to `ember-source/dist/ember-template-compiler` + module.exports = { plugins: [ '@embroider/addon-dev/template-colocation-plugin', @@ -13,9 +17,6 @@ module.exports = { someAstTransformPlugin, './path/to/another-template-transform-plugin', ], - compilerPath: require.resolve( - 'ember-source/dist/ember-template-compiler' - ), }, ], ['@babel/plugin-proposal-decorators', { legacy: true }], diff --git a/packages/addon-dev/src/template-transform-plugin.ts b/packages/addon-dev/src/template-transform-plugin.ts index 4c5e8c516..000a84e53 100644 --- a/packages/addon-dev/src/template-transform-plugin.ts +++ b/packages/addon-dev/src/template-transform-plugin.ts @@ -1,15 +1,14 @@ import make from '@embroider/core/src/babel-plugin-stage1-inline-hbs'; import { TemplateCompiler, TemplateCompilerParams } from '@embroider/core'; import { getEmberExports } from '@embroider/core/src/load-ember-template-compiler'; -import { EmberENV } from '@embroider/core'; - -type TemplateTransform = () => { name: string; visitor: {} }; +export type TemplateTransform = () => { name: string; visitor: {} }; export type TemplateTransformPlugin = TemplateTransform | string; export interface Options { - astTransforms: TemplateTransformPlugin[] | undefined; - compilerPath: string; - EmberENV: EmberENV; + // An array of either Glimmer AST plugins or paths that can be resolved to a plugin. + astTransforms?: TemplateTransformPlugin[]; + // Defaults to 'ember-source/dist/ember-template-compiler' + compilerPath?: string; } function resolvePlugins(plugins: TemplateTransformPlugin[]) { @@ -22,15 +21,21 @@ function resolvePlugins(plugins: TemplateTransformPlugin[]) { } export default make((options: Options) => { - let { compilerPath, astTransforms: somePlugins = [], ...opts } = options; + let { + astTransforms: somePlugins = [], + compilerPath = 'ember-source/dist/ember-template-compiler', + } = options; + + compilerPath = require.resolve(compilerPath); + const astTransforms: TemplateTransform[] = resolvePlugins(somePlugins); const params: TemplateCompilerParams = { + EmberENV: {}, loadEmberTemplateCompiler: () => getEmberExports(compilerPath), plugins: { ast: astTransforms, }, - ...opts, }; return new TemplateCompiler(params); diff --git a/packages/addon-dev/tests/template-transform-plugin.test.ts b/packages/addon-dev/tests/template-transform-plugin.test.ts index fca1fcdc4..55376f48f 100644 --- a/packages/addon-dev/tests/template-transform-plugin.test.ts +++ b/packages/addon-dev/tests/template-transform-plugin.test.ts @@ -39,7 +39,6 @@ describe('template-transform-plugin', () => { const opts: Options = { astTransforms: options?.astTransforms, compilerPath: emberTemplateCompilerPath(), - EmberENV: {}, }; plugins = [[templateTransformBabelPlugin, opts]]; } diff --git a/yarn.lock b/yarn.lock index 5fc8e9738..d5bda6362 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1714,6 +1714,13 @@ dependencies: "@simple-dom/interface" "^1.4.0" +"@glimmer/interfaces@0.84.2": + version "0.84.2" + resolved "https://registry.yarnpkg.com/@glimmer/interfaces/-/interfaces-0.84.2.tgz#764cf92c954adcd1a851e5dc68ec1f6b654dc3bd" + integrity sha512-tMZxQpOddUVmHEOuripkNqVR7ba0K4doiYnFd4WyswqoHPlxqpBujbIamQ+bWCWEF0U4yxsXKa31ekS/JHkiBQ== + dependencies: + "@simple-dom/interface" "^1.4.0" + "@glimmer/interfaces@^0.42.2": version "0.42.2" resolved "https://registry.yarnpkg.com/@glimmer/interfaces/-/interfaces-0.42.2.tgz#9cf8d6f8f5eee6bfcfa36919ca68ae716e1f78db" @@ -1801,6 +1808,16 @@ "@handlebars/parser" "^1.1.0" simple-html-tokenizer "^0.5.10" +"@glimmer/syntax@^0.84.2": + version "0.84.2" + resolved "https://registry.yarnpkg.com/@glimmer/syntax/-/syntax-0.84.2.tgz#a3f65e51eec20f6adb79c6159d1ad1166fa5bccd" + integrity sha512-SPBd1tpIR9XeaXsXsMRCnKz63eLnIZ0d5G9QC4zIBFBC3pQdtG0F5kWeuRVCdfTIFuR+5WBMfk5jvg+3gbQhjg== + dependencies: + "@glimmer/interfaces" "0.84.2" + "@glimmer/util" "0.84.2" + "@handlebars/parser" "~2.0.0" + simple-html-tokenizer "^0.5.11" + "@glimmer/tracking@^1.0.0", "@glimmer/tracking@^1.0.3", "@glimmer/tracking@^1.0.4": version "1.1.2" resolved "https://registry.yarnpkg.com/@glimmer/tracking/-/tracking-1.1.2.tgz#74e71be07b0a7066518d24044d2665d0cf8281eb" @@ -1827,6 +1844,15 @@ "@glimmer/interfaces" "0.80.0" "@simple-dom/interface" "^1.4.0" +"@glimmer/util@0.84.2": + version "0.84.2" + resolved "https://registry.yarnpkg.com/@glimmer/util/-/util-0.84.2.tgz#2711ba40f25f44b2ea309cad49f5c2622c6211bc" + integrity sha512-VbhzE2s4rmU+qJF3gGBTL1IDjq+/G2Th51XErS8MQVMCmE4CU2pdwSzec8PyOowqCGUOrVIWuMzEI6VoPM4L4w== + dependencies: + "@glimmer/env" "0.1.7" + "@glimmer/interfaces" "0.84.2" + "@simple-dom/interface" "^1.4.0" + "@glimmer/util@^0.42.2": version "0.42.2" resolved "https://registry.yarnpkg.com/@glimmer/util/-/util-0.42.2.tgz#9ca1631e42766ea6059f4b49d0bdfb6095aad2c4" @@ -5562,7 +5588,15 @@ browserify-zlib@^0.2.0: dependencies: pako "~1.0.5" -browserslist@^3.2.6, browserslist@^4.0.0, browserslist@^4.14.0, browserslist@^4.14.5, browserslist@^4.20.2, browserslist@^4.20.3: +browserslist@^3.2.6: + version "3.2.8" + resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-3.2.8.tgz#b0005361d6471f0f5952797a76fc985f1f978fc6" + integrity sha512-WHVocJYavUwVgVViC0ORikPHQquXwVh939TaelZ4WDqpWgTX/FsGhl/+P4qBUAGcRvtOgDgC+xftNWWp2RUTAQ== + dependencies: + caniuse-lite "^1.0.30000844" + electron-to-chromium "^1.3.47" + +browserslist@^4.0.0, browserslist@^4.14.5, browserslist@^4.20.2, browserslist@^4.20.3: version "4.20.3" resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.20.3.tgz#eb7572f49ec430e054f56d52ff0ebe9be915f8bf" integrity sha512-NBhymBQl1zM0Y5dQT/O+xiLP9/rzOIQdKM/eMJBAq7yBgaB6krIYLGejrwVYnSHZdqjscB1SPuAjHwxjvN6Wdg== @@ -5789,6 +5823,11 @@ caniuse-lite@^1.0.0, caniuse-lite@^1.0.30001332: resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001342.tgz#87152b1e3b950d1fbf0093e23f00b6c8e8f1da96" integrity sha512-bn6sOCu7L7jcbBbyNhLg0qzXdJ/PMbybZTH/BA6Roet9wxYRm6Tr9D0s0uhLkOZ6MSG+QU6txUgdpr3MXIVqjA== +caniuse-lite@^1.0.30000844: + version "1.0.30001344" + resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001344.tgz#8a1e7fdc4db9c2ec79a05e9fd68eb93a761888bb" + integrity sha512-0ZFjnlCaXNOAYcV7i+TtdKBp0L/3XEU2MF/x6Du1lrh+SRX4IfzIVL4HNJg5pB2PmFb8rszIGyOvsZnqqRoc2g== + capture-exit@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/capture-exit/-/capture-exit-2.0.0.tgz#fb953bfaebeb781f62898239dabb426d08a509a4" @@ -7037,6 +7076,11 @@ ee-first@1.1.1: resolved "https://registry.yarnpkg.com/ee-first/-/ee-first-1.1.1.tgz#590c61156b0ae2f4f0255732a158b266bc56b21d" integrity sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0= +electron-to-chromium@^1.3.47: + version "1.4.143" + resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.4.143.tgz#10f1bb595ad6cd893c05097039c685dcf5c8e30c" + integrity sha512-2hIgvu0+pDfXIqmVmV5X6iwMjQ2KxDsWKwM+oI1fABEOy/Dqmll0QJRmIQ3rm+XaoUa/qKrmy5h7LSTFQ6Ldzg== + electron-to-chromium@^1.4.118: version "1.4.137" resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.4.137.tgz#186180a45617283f1c012284458510cd99d6787f" @@ -15071,7 +15115,7 @@ qunit-dom@^1.6.0: ember-cli-babel "^7.23.0" ember-cli-version-checker "^5.1.1" -qunit@^2.14.1, qunit@^2.16.0: +qunit@^2.16.0: version "2.19.1" resolved "https://registry.yarnpkg.com/qunit/-/qunit-2.19.1.tgz#eb1afd188da9e47f07c13aa70461a1d9c4505490" integrity sha512-gSGuw0vErE/rNjnlBW/JmE7NNubBlGrDPQvsug32ejYhcVFuZec9yoU0+C30+UgeCGwq6Ap89K65dMGo+kDGZQ== @@ -16180,7 +16224,7 @@ simple-dom@^1.4.0: "@simple-dom/serializer" "^1.4.0" "@simple-dom/void-map" "^1.4.0" -simple-html-tokenizer@^0.5.10, simple-html-tokenizer@^0.5.8: +simple-html-tokenizer@^0.5.10, simple-html-tokenizer@^0.5.11, simple-html-tokenizer@^0.5.8: version "0.5.11" resolved "https://registry.yarnpkg.com/simple-html-tokenizer/-/simple-html-tokenizer-0.5.11.tgz#4c5186083c164ba22a7b477b7687ac056ad6b1d9" integrity sha512-C2WEK/Z3HoSFbYq8tI7ni3eOo/NneSPRoPpcM7WdLjFOArFuyXEjAoCdOC3DgMfRyziZQ1hCNR4mrNdWEvD0og== From cac272003cd4f9573e9adc3722498382554c3d91 Mon Sep 17 00:00:00 2001 From: Matthew Edwards Date: Thu, 9 Jun 2022 11:31:04 -0700 Subject: [PATCH 9/9] Added ember-source as peerDependenciesMeta --- packages/addon-dev/package.json | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/packages/addon-dev/package.json b/packages/addon-dev/package.json index 7c63ae891..ce18863f6 100644 --- a/packages/addon-dev/package.json +++ b/packages/addon-dev/package.json @@ -50,6 +50,11 @@ "peerDependencies": { "ember-source": "*" }, + "peerDependenciesMeta": { + "ember-source": { + "optional": true + } + }, "engines": { "node": "12.* || 14.* || >= 16" },