Skip to content

Commit

Permalink
Support template-only imports
Browse files Browse the repository at this point in the history
  • Loading branch information
NullVoxPopuli committed Feb 18, 2022
1 parent 7e5b1fe commit bfdcdac
Show file tree
Hide file tree
Showing 2 changed files with 82 additions and 13 deletions.
80 changes: 73 additions & 7 deletions packages/addon-dev/src/rollup-hbs-plugin.ts
@@ -1,23 +1,89 @@
import { createFilter } from '@rollup/pluginutils';
import type { Plugin } from 'rollup';
import { pathExists } from 'fs-extra';
import { readFileSync } from 'fs';
import path from 'path';

import type { Plugin } from 'rollup';

const backtick = '`';

export default function rollupHbsPlugin(): Plugin {
const filter = createFilter('**/*.hbs');

return {
name: 'rollup-hbs-plugin',
load(id: string) {
async load(id: string) {
if (!filter(id)) return;
let input = readFileSync(id, 'utf8');
let code =
`import { hbs } from 'ember-cli-htmlbars';\n` +
`export default hbs${backtick}${input}${backtick};`;

if (await isTemplateOnly(id)) {
return { code: getTemplateOnly(id), id };
}

// For templates with a backing class
return {
code,
code: getTemplateFactory(id),
id: id + '.js',
};
},

// template-only components may be imported
async resolveId(source, importer, options) {
let resolution = await this.resolve(source, importer, {
...options,
skipSelf: true,
});

let ext = path.extname(source);

// For hbs files, we _might_ have a template-only situation
if (resolution && ext !== '.hbs') return resolution;
if (!importer) return null;

// source may or may not have '.hbs' on the path
let dir = path.dirname(importer);
let nameWithExt = ext ? source : source + '.hbs';
let maybeHbs = path.join(dir, nameWithExt);

resolution = await this.resolve(maybeHbs, importer, {
...options,
skipSelf: true,
});

if (resolution) return resolution;

return null;
},
};
}

async function isTemplateOnly(hbsPath: string) {
let jsPath = hbsPath.replace(/\.hbs$/, '.js')
let tsPath = hbsPath.replace(/\.hbs$/, '.ts')

let hasJs = await pathExists(jsPath);
let hasTs = await pathExists(tsPath);

let hasClass = hasJs || hasTs;

return !hasClass;
}

function getTemplateOnly(hbsPath: string) {
let input = readFileSync(hbsPath, 'utf8');
let code =
`import { hbs } from 'ember-cli-htmlbars';\n` +
`import templateOnly from '@ember/component/template-only';\n` +
`import { setComponentTemplate } from '@ember/component';\n` +
`export default setComponentTemplate(\n` +`hbs${backtick}${input.trim()}${backtick}, templateOnly());`;

return code;
}

function getTemplateFactory(hbsPath: string) {
let input = readFileSync(hbsPath, 'utf8');
let code =
`import { hbs } from 'ember-cli-htmlbars';\n` +
`export default hbs${backtick}${input.trim()}${backtick};`;

return code;
}
15 changes: 9 additions & 6 deletions packages/addon-dev/src/rollup-public-entrypoints.ts
@@ -1,9 +1,10 @@
import walkSync from 'walk-sync';
import type { Plugin } from 'rollup';
import { join } from 'path';

import type { Plugin } from 'rollup';

function normalizeFileExt(fileName: string) {
return fileName.replace(/\.ts|\.gts|\.gjs$/, '.js');
return fileName.replace(/\.ts|\.hbs|\.gts|\.gjs$/, '.js');
}

export default function publicEntrypoints(args: {
Expand All @@ -12,10 +13,12 @@ export default function publicEntrypoints(args: {
}): Plugin {
return {
name: 'addon-modules',
buildStart() {
for (let name of walkSync(args.srcDir, {
globs: args.include,
})) {
async buildStart() {
let matches = walkSync(args.srcDir, {
globs: [...args.include],
});

for (let name of matches) {
this.emitFile({
type: 'chunk',
id: join(args.srcDir, name),
Expand Down

0 comments on commit bfdcdac

Please sign in to comment.