-
Notifications
You must be signed in to change notification settings - Fork 143
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #1199 from wondersloth/medwards/babel-template-tra…
…nsform-plugin Add babel plugin for preprocessing templates with ast transforms
- Loading branch information
Showing
13 changed files
with
313 additions
and
19 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
module.exports = { | ||
testEnvironment: 'node', | ||
testMatch: [ | ||
'<rootDir>/tests/**/*.test.js', | ||
], | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
// Some addons need to transform their templates before they have a portable format. | ||
// 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', | ||
[ | ||
'@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', | ||
], | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,42 @@ | ||
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'; | ||
|
||
export type TemplateTransform = () => { name: string; visitor: {} }; | ||
export type TemplateTransformPlugin = TemplateTransform | string; | ||
export interface Options { | ||
// 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[]) { | ||
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 make((options: 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, | ||
}, | ||
}; | ||
|
||
return new TemplateCompiler(params); | ||
}); |
150 changes: 150 additions & 0 deletions
150
packages/addon-dev/tests/template-transform-plugin.test.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,150 @@ | ||
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'; | ||
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?: { | ||
astTransforms: TemplateTransformPlugin[]; | ||
}) { | ||
const opts: Options = { | ||
astTransforms: options?.astTransforms, | ||
compilerPath: emberTemplateCompilerPath(), | ||
}; | ||
plugins = [[templateTransformBabelPlugin, opts]]; | ||
} | ||
|
||
allBabelVersions({ | ||
babelConfig() { | ||
return { | ||
plugins, | ||
}; | ||
}, | ||
createTests(transform) { | ||
afterEach(function () { | ||
plugins = 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('<span>{{@phrase}}</span>'); | ||
let output = transform(code); | ||
expect(output).toMatch( | ||
/import { hbs } from ['"]ember-cli-htmlbars['"];/ | ||
); | ||
expect(output).toMatch( | ||
/export default hbs\(['"]\<naps\>{{@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('<span>{{@phrase}}</span>'); | ||
|
||
let output = transform(code); | ||
|
||
expect(output).toMatch( | ||
/import { hbs } from ['"]ember-cli-htmlbars['"];/ | ||
); | ||
expect(output).toMatch( | ||
/export default hbs\(['"]\<naps\>{{@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('<span>{{@phrase}}</span>');`; | ||
|
||
let output = transform(code); | ||
|
||
expect(output).toMatch( | ||
/import { hbs as render } from ['"]ember-cli-htmlbars['"];/ | ||
); | ||
expect(output).toMatch( | ||
/export default render\(['"]\<naps\>{{@phrase}}\<\/naps\>['"]\);/ | ||
); | ||
}); | ||
}, | ||
}); | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.