Skip to content

Commit

Permalink
Merge pull request #1295 from embroider-build/kiosion/main
Browse files Browse the repository at this point in the history
Update compat to check for both *.hbs & *.hbs.js
  • Loading branch information
ef4 committed Nov 28, 2022
2 parents e0bd093 + f74ece7 commit 3ef6696
Show file tree
Hide file tree
Showing 5 changed files with 78 additions and 30 deletions.
4 changes: 4 additions & 0 deletions .gitignore
Expand Up @@ -65,3 +65,7 @@ tmp/

# scenario tester debugging output
tests/scenarios/output/

# Sys files
.DS_Store
*.swp
40 changes: 22 additions & 18 deletions packages/compat/src/synthesize-template-only-components.ts
Expand Up @@ -7,24 +7,26 @@ import { remove, outputFileSync, pathExistsSync } from 'fs-extra';
const source = `import templateOnlyComponent from '@ember/component/template-only';
export default templateOnlyComponent();`;

const templateExtension = '.hbs';

const jsExtensions = ['.js', '.ts', '.mjs', '.mts'];

export default class SynthesizeTemplateOnlyComponents extends Plugin {
private emitted = new Set() as Set<string>;
private allowedPaths: string[];
private templateExtensions: string[];

constructor(tree: Node, private allowedPaths: string[]) {
constructor(tree: Node, params: { allowedPaths: string[]; templateExtensions: string[] }) {
super([tree], {
annotation: `synthesize-template-only-components:${allowedPaths.join(':')}`,
annotation: `synthesize-template-only-components:${params.allowedPaths.join(':')}`,
persistentOutput: true,
needsCache: false,
});
this.allowedPaths = params.allowedPaths;
this.templateExtensions = params.templateExtensions;
}

async build() {
for (let dir of this.allowedPaths) {
let { needed, seen } = crawl(join(this.inputPaths[0], dir));
let { needed, seen } = this.crawl(join(this.inputPaths[0], dir));
for (let file of needed) {
let fullName = join(this.outputPath, dir, file);
if (seen.has(file)) {
Expand Down Expand Up @@ -53,22 +55,24 @@ export default class SynthesizeTemplateOnlyComponents extends Plugin {
this.emitted.delete(filename);
}
}
}

function crawl(dir: string) {
const needed = new Set<string>();
const seen = new Set<string>();
if (pathExistsSync(dir)) {
for (let file of walkSync(dir, { directories: false })) {
if (file.endsWith(templateExtension)) {
needed.add(file.slice(0, -1 * templateExtension.length));
} else {
const jsExtension = jsExtensions.find(ext => file.endsWith(ext));
if (jsExtension) {
seen.add(file.slice(0, -1 * jsExtension.length));
private crawl(dir: string) {
const needed = new Set<string>();
const seen = new Set<string>();
if (pathExistsSync(dir)) {
for (let file of walkSync(dir, { directories: false })) {
for (const templateExtension of this.templateExtensions) {
if (file.endsWith(templateExtension)) {
needed.add(file.slice(0, -1 * templateExtension.length));
} else {
const jsExtension = jsExtensions.find(ext => file.endsWith(ext));
if (jsExtension) {
seen.add(file.slice(0, -1 * jsExtension.length));
}
}
}
}
}
return { needed, seen };
}
return { needed, seen };
}
8 changes: 7 additions & 1 deletion packages/compat/src/v1-addon.ts
Expand Up @@ -724,7 +724,13 @@ export default class V1Addon {
if (!tree) {
return;
}
let templateOnlyComponents: Node = new SynthesizeTemplateOnlyComponents(tree, ['components']);
let templateOnlyComponents: Node = new SynthesizeTemplateOnlyComponents(tree, {
allowedPaths: ['components'],

// if an addon has custom AST transforms, stage1 can rewrite .hbs to
// .hbs.js
templateExtensions: ['.hbs', '.hbs.js'],
});
if (!this.addonOptions.staticAddonTrees) {
let filenames: string[] = [];
let templateOnlyComponentNames: string[] = [];
Expand Down
4 changes: 3 additions & 1 deletion packages/compat/src/v1-app.ts
Expand Up @@ -657,7 +657,9 @@ export default class V1App {

let trees: Node[] = [];
trees.push(appTree);
trees.push(new SynthesizeTemplateOnlyComponents(appTree, ['components']));
trees.push(
new SynthesizeTemplateOnlyComponents(appTree, { allowedPaths: ['components'], templateExtensions: ['.hbs'] })
);

trees.push(configReplaced);
if (testsTree) {
Expand Down
52 changes: 42 additions & 10 deletions tests/scenarios/stage1-test.ts
Expand Up @@ -6,6 +6,8 @@ import { loadFromFixtureData } from './helpers';
import { dummyAppScenarios, baseAddon, appScenarios } from './scenarios';
import { PreparedApp } from 'scenario-tester';
import QUnit from 'qunit';
import { expectFilesAt, ExpectFile } from '@embroider/test-support';

const { module: Qmodule, test } = QUnit;

appScenarios
Expand Down Expand Up @@ -128,6 +130,14 @@ appScenarios
merge(addon.files, {
addon: {
components: {
'template-only.hbs': `<div data-test="template-only"></div>`,
'colocated.js': `
import Component from '@glimmer/component';
export default class extends Component {
identifier = "i-am-colocated";
}
`,
'colocated.hbs': `<div data-test={{this.identifier}}></div>`,
'has-inline-template.js': `
import Component from '@ember/component';
import hbs from 'htmlbars-inline-precompile';
Expand Down Expand Up @@ -160,23 +170,45 @@ appScenarios
workspaceDir = fs.readFileSync(join(app.dir, 'dist', '.stage1-output'), 'utf8');
});

test('component with inline template', function (assert) {
let fileContents = fs.readFileSync(
join(workspaceDir, 'node_modules/my-addon/components/has-inline-template.js')
);
assert.ok(
fileContents.includes('hbs`<div class={{embroider-sample-transforms-result}}>Inline</div>'),
let expectFile: ExpectFile;
hooks.beforeEach(assert => {
expectFile = expectFilesAt(workspaceDir, { qunit: assert });
});

test('component with inline template', function () {
let file = expectFile('node_modules/my-addon/components/has-inline-template.js');

file.matches(
'hbs`<div class={{embroider-sample-transforms-result}}>Inline</div>',
'tagged template is still hbs and custom transforms have run'
);
assert.ok(
/hbs\(["']<div class={{embroider-sample-transforms-result}}>Extra<\/div>["']\)/.test(fileContents.toString()),

file.matches(
/hbs\(["']<div class={{embroider-sample-transforms-result}}>Extra<\/div>["']\)/,
'called template is still hbs and custom transforms have run'
);
assert.ok(
/<span>{{macroDependencySatisfies ['"]ember-source['"] ['"]>3['"]}}<\/span>/.test(fileContents.toString()),

file.matches(
/<span>{{macroDependencySatisfies ['"]ember-source['"] ['"]>3['"]}}<\/span>/,
'template macros have not run'
);
});

test('component with colocated template', function () {
// co-located pairs are left alone in stage1 because we deal with them
// in stage3
expectFile('node_modules/my-addon/components/colocated.js').matches('i-am-colocated');
expectFile('node_modules/my-addon/components/colocated.hbs.js').exists();
});

test('template-only component', function () {
expectFile('node_modules/my-addon/components/template-only.js').matches(
'export default templateOnlyComponent()'
);
expectFile('node_modules/my-addon/components/template-only.hbs.js').matches(
'export default precompileTemplate'
);
});
});
});

Expand Down

0 comments on commit 3ef6696

Please sign in to comment.