Package Exports
- babel-plugin-ember-template-compilation
- babel-plugin-ember-template-compilation/browser
- babel-plugin-ember-template-compilation/node
Readme
babel-plugin-ember-template-compilation
Babel plugin that implements Ember's low-level template-compilation API.
Requirements
- Node 12+ (when used in Node, but we also support in-browser usage)
- Babel 7
- the output works with ember-source 3.27+. For older Ember versions, see babel-plugin-htmlbars-inline-precompile instead.
Usage
This plugin implements precompileTemplate from RFC 496:
import { precompileTemplate } from '@ember/template-compilation';For backward compatibility, it also has an enableLegacyModules option that can enable each of these widely-used older patterns:
import { hbs } from 'ember-cli-htmlbars';
import hbs from 'ember-cli-htmlbars-inline-precompile';
import hbs from 'htmlbars-inline-precompile';Common Options
This package has both a Node implementation and a portable implementation that works in browsers. Both implementations share these common options:
interface Options {
// Allows you to remap what imports will be emitted in our compiled output. By
// example:
//
// outputModuleOverrides: {
// '@ember/template-factory': {
// createTemplateFactory: ['createTemplateFactory', '@glimmer/core'],
// }
// }
//
// Normal Ember apps shouldn't need this, it exists to support other
// environments like standalone GlimmerJS
outputModuleOverrides?: Record<string, Record<string, [string, string]>>;
// By default, this plugin implements only Ember's stable public API for
// template compilation, which is:
//
// import { precompileTemplate } from '@ember/template-compilation';
//
// But historically there are several other importable syntaxes in widespread
// use, and we can enable those too by including their module names in this
// list.
enableLegacyModules?: LegacyModuleName[];
}
type LegacyModuleName =
| 'ember-cli-htmlbars'
| 'ember-cli-htmlbars-inline-precompile'
| 'htmlbars-inline-precompile';Node Options
When used in Node, the Options are extended to include:
interface NodeOptions extends Options {
// The on-disk path to a module that provides a `precompile` function as
// defined below. You need to either set `precompilePath` or set `precompile`.
precompilerPath?: string;
// A precompile function that invokes Ember's template compiler.
//
// Options handling rules:
//
// - we add `content`, which is the original string form of the template
// - we add `meta.jsutils`, which gives AST transform plugins access to methods for manipulating the surrounding javascript scope. See "JSUtils" below.
// - we have special parsing for `scope` which becomes `locals` when passed
// to your precompile
// - anything else the user passes to `precompileTemplate` will be passed
// through to your `precompile`.
precompile?: EmberPrecompile;
}
type EmberPrecompile = (templateString: string, options: Record<string, unknown>) => string;Browser Options
For use in non-Node environments including browsers, when you import from this package you get a factory function that takes a callback and returns the plugin. Your callback receives the babel plugin options and should return the precompile: EmberPrecompile function as defined above.
import makePlugin from 'babel-plugin-ember-template-compilation';
import * as babel from '@babel/core';
babel.transform(someCode, { plugins: [makePlugin(loadTemplateCompiler)] });JSUtils: Manipulating Javascript from within AST transforms
AST transforms are plugins for modifying HBS templates at build time. Because those templates are embedded in Javascript and can access the Javascript scope, an AST plugin may want to introduce some new things into Javascript scope. That is what the JSUtils API is for.
Your AST transform can access the JSUtils API via env.meta.jsutils. Here's an example transform.
function myAstTransform(env) {
return {
name: 'my-ast-transform',
visitor: {
PathExpression(node, path) {
if (node.original === 'onePlusOne') {
let name = env.meta.jsutils.bindExpression('1+1', path, { nameHint: 'two' });
return env.syntax.builders.path(name);
}
},
},
};
}The example transform above would rewrite:
import { precompileTemplate } from '@ember/template-compilation';
precompileTemplate('<Counter @value={{onePlusOne}} />>');To:
import { precompileTemplate } from '@ember/template-compilation';
let two = 1 + 1;
precompileTemplate('<Counter @value={{two}} />', { scope: () => ({ two }) });See the jsdoc comments in js-utils.js for details on the methods available.
Acknowledgement / History
This repo derives from https://github.com/ember-cli/babel-plugin-htmlbars-inline-precompile