Skip to content

Commit

Permalink
[BUGFIX release] Expose @glimmer/syntax from template compiler priv…
Browse files Browse the repository at this point in the history
…ately for use in Embroider.

This enables Embroider to remove some gnarly hacks (or at least only
resort to them when operating on older Ember).
  • Loading branch information
rwjblue committed Feb 25, 2021
1 parent 3aff3c5 commit b46eee7
Show file tree
Hide file tree
Showing 3 changed files with 117 additions and 4 deletions.
8 changes: 8 additions & 0 deletions packages/ember-template-compiler/index.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { ENV } from '@ember/-internals/environment';
import { FEATURES } from '@ember/canary-features';
import * as _GlimmerSyntax from '@glimmer/syntax';
import VERSION from 'ember/version';
import require from 'require';

Expand Down Expand Up @@ -28,12 +29,19 @@ export { default as precompile } from './lib/system/precompile';
export { default as compile } from './lib/system/compile';
export {
default as compileOptions,
buildCompileOptions as _buildCompileOptions,
transformsFor as _transformsFor,
registerPlugin,
unregisterPlugin,
} from './lib/system/compile-options';
export { RESOLUTION_MODE_TRANSFORMS, STRICT_MODE_TRANSFORMS } from './lib/plugins/index';
export { EmberPrecompileOptions } from './lib/types';

export { preprocess as _preprocess, print as _print } from '@glimmer/syntax';
export { precompile as _precompile } from '@glimmer/compiler';

export { _GlimmerSyntax, VERSION };

// used to bootstrap templates
import './lib/system/bootstrap';

Expand Down
21 changes: 17 additions & 4 deletions packages/ember-template-compiler/lib/system/compile-options.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,9 @@ function malformedComponentLookup(string: string) {
return string.indexOf('::') === -1 && string.indexOf(':') > -1;
}

export default function compileOptions(
_options: Partial<EmberPrecompileOptions> = {}
): PrecompileOptions {
export function buildCompileOptions(
_options: Partial<EmberPrecompileOptions>
): EmberPrecompileOptions {
let options: EmberPrecompileOptions = assign(
{ meta: {}, isProduction: false, plugins: { ast: [] } },
_options,
Expand All @@ -42,7 +42,20 @@ export default function compileOptions(
meta.moduleName = options.moduleName;
}

let builtInPlugins = options.strictMode ? STRICT_MODE_TRANSFORMS : RESOLUTION_MODE_TRANSFORMS;
return options;
}

export function transformsFor(options: EmberPrecompileOptions): readonly PluginFunc[] {
return EMBER_STRICT_MODE && options.strictMode
? STRICT_MODE_TRANSFORMS
: RESOLUTION_MODE_TRANSFORMS;
}

export default function compileOptions(
_options: Partial<EmberPrecompileOptions> = {}
): PrecompileOptions {
let options = buildCompileOptions(_options);
let builtInPlugins = transformsFor(options);

if (!_options.plugins) {
options.plugins = { ast: [...USER_PLUGINS, ...builtInPlugins] };
Expand Down
92 changes: 92 additions & 0 deletions packages/ember-template-compiler/tests/basic-usage-test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
import {
_buildCompileOptions,
_preprocess,
_print,
registerPlugin,
unregisterPlugin,
} from '../index';
import { moduleFor, RenderingTestCase } from 'internal-test-helpers';

function reverseElementNodeTag() {
return {
name: 'reverse-element-node-tag',
visitor: {
ElementNode(node) {
node.tag = node.tag.split('').reverse().join('');
},
},
};
}

function removeDataTest() {
return {
name: 'remove-data-test',

visitor: {
ElementNode(node) {
for (let i = 0; i < node.attributes.length; i++) {
let attribute = node.attributes[i];

if (attribute.name === 'data-test') {
node.attributes.splice(i, 1);
}
}
},
},
};
}

moduleFor(
'ember-template-compiler: Embroider-like compilation',
class extends RenderingTestCase {
afterEach() {
expectDeprecation(() => {
unregisterPlugin('ast', removeDataTest);
}, /unregisterPlugin is deprecated, please pass plugins directly via `compile` and\/or `precompile`/);
return super.afterEach();
}

'@test can process a subset of AST plugins and print'(assert) {
let template = '<div data-test="foo" data-blah="derp" class="hahaha">&nbsp;</div>';

// build up options including strictMode default values, customizeComponentName, meta.moduleName, etc
let options = _buildCompileOptions({
mode: 'codemod',
moduleName: 'components/foo',
plugins: { ast: [removeDataTest] },
});

let transformedTemplateAST = _preprocess(template, options);

// print back to a handlebars string
let result = _print(transformedTemplateAST, { entityEncoding: 'raw' });

assert.equal(result, '<div data-blah="derp" class="hahaha">&nbsp;</div>');
}

'@test registerPlugin based transforms can be avoided'(assert) {
expectDeprecation(() => {
registerPlugin('ast', removeDataTest);
}, /registerPlugin is deprecated, please pass plugins directly via `compile` and\/or `precompile`/);

let template = '<div data-test="foo" data-blah="derp" class="hahaha">&nbsp;</div>';

// build up options including strictMode default values, customizeComponentName, meta.moduleName, etc
let options = _buildCompileOptions({
mode: 'codemod',
moduleName: 'components/foo',
plugins: {
ast: [reverseElementNodeTag],
},
});

let transformedTemplateAST = _preprocess(template, options);

// print back to a handlebars string
let result = _print(transformedTemplateAST, { entityEncoding: 'raw' });

// only reverseElementNodeTag has ran, **not** removeDataTest
assert.equal(result, '<vid data-test="foo" data-blah="derp" class="hahaha">&nbsp;</vid>');
}
}
);

0 comments on commit b46eee7

Please sign in to comment.