Skip to content

Commit

Permalink
Merge pull request #1867 from embroider-build/public-assets-namespace
Browse files Browse the repository at this point in the history
add a namespace option for public-assets plugin
  • Loading branch information
mansona authored Apr 10, 2024
2 parents cf2bacf + e00d4a9 commit 5acd254
Show file tree
Hide file tree
Showing 5 changed files with 130 additions and 15 deletions.
3 changes: 2 additions & 1 deletion docs/v2-faq.md
Original file line number Diff line number Diff line change
Expand Up @@ -141,7 +141,8 @@ This is done by adding some meta data to the addon's `package.json`, specifying
}
```

If you have many files you want to expose this way, you can instead add the `addon.publicAssets()` plugin from `@embroider/addon-dev` to your Rollup config to automate the generation of this mapping data.
If you have many files you want to expose this way, you can instead add the `addon.publicAssets()` plugin from `@embroider/addon-dev` to your Rollup config to automate the generation of this mapping data. This rollup plugin will automatically prefix your public assets with a folder name that matches your addon packages name, this is to prevent any name clashes between addons. You can read more about it in the docs for the addon-dev rollup plugin utilities https://github.com/embroider-build/embroider/tree/main/packages/addon-dev#rollup-utilities


## Build setup

Expand Down
4 changes: 4 additions & 0 deletions packages/addon-dev/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,10 @@ For a guide on porting a V1 addon to V2, see https://github.com/embroider-build/
2. Copy the `./sample-rollup.config.js` in this repo to your own `rollup.config.js`.
3. Copy the `./sample-babel.config.json` in this repo to your own `babel.config.json`.

### addon.publicAssets(path <required>, options)

A rollup plugin to expose a folder of assets. `path` is a required to define which folder to expose. `options.include` is a glob pattern passed to `walkSync.include` to pick files. `options.exlude` is a glob pattern passed to `walkSync.ignore` to exclude files. `options.namespace` is the namespace to expose files, defaults to the package name

## addon-dev command

The `addon-dev` command helps with common tasks in v2 addons.
Expand Down
30 changes: 28 additions & 2 deletions packages/addon-dev/src/rollup-public-assets.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,34 @@
import { readJsonSync, writeJsonSync } from 'fs-extra';
import walkSync from 'walk-sync';
import type { Plugin } from 'rollup';
import { resolve, join } from 'path/posix';

export interface PublicAssetsOptions {
/**
* glob pattern passed to `walkSync.include` to pick files
*/
include?: string[];

/**
* glob pattern passed to `walkSync.ignore` to exclude files
*/
exclude?: string[];

/**
* namespace to expose files
*/
namespace?: string;
}

/**
* A rollup plugin to expose a folder of assets
*
* @param path - the public folder that you want to add as public assets
* @returns
*/
export default function publicAssets(
path: string,
opts: { include: string[]; exclude: string[] }
opts?: PublicAssetsOptions
): Plugin {
const includeGlobPatterns = opts?.include;
const excludedGlobPatterns = opts?.exclude || [];
Expand All @@ -27,7 +51,9 @@ export default function publicAssets(
});
const publicAssets: Record<string, string> = filenames.reduce(
(acc: Record<string, string>, v): Record<string, string> => {
acc[`./${path}/${v}`] = ['/', pkg.name, '/', path, '/', v].join('');
acc[`./${path}/${v}`] = resolve(
'/' + join(opts?.namespace ?? pkg.name, path, v)
);
return acc;
},
{}
Expand Down
7 changes: 5 additions & 2 deletions packages/addon-dev/src/rollup.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,10 @@ import type { Options as DelOptions } from 'rollup-plugin-delete';
import { default as clean } from 'rollup-plugin-delete';
import { default as keepAssets } from './rollup-keep-assets';
import { default as dependencies } from './rollup-addon-dependencies';
import { default as publicAssets } from './rollup-public-assets';
import {
default as publicAssets,
type PublicAssetsOptions,
} from './rollup-public-assets';
import type { Plugin } from 'rollup';

export class Addon {
Expand Down Expand Up @@ -102,7 +105,7 @@ export class Addon {
return dependencies();
}

publicAssets(path: string, opts: { include: string[]; exclude: string[] }) {
publicAssets(path: string, opts?: PublicAssetsOptions) {
return publicAssets(path, opts);
}
}
101 changes: 91 additions & 10 deletions tests/scenarios/v2-addon-dev-test.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import path from 'path';
import { appScenarios, baseV2Addon } from './scenarios';
import { PreparedApp } from 'scenario-tester';
import { PreparedApp, type Project } from 'scenario-tester';
import QUnit from 'qunit';
import merge from 'lodash/merge';
import type { ExpectFile } from '@embroider/test-support/file-assertions/qunit';
Expand Down Expand Up @@ -74,6 +74,7 @@ appScenarios
addon.hbs(),
addon.gjs(),
addon.dependencies(),
addon.publicAssets('public'),
babel({ babelHelpers: 'bundled', extensions: ['.js', '.hbs', '.gjs'] }),
Expand Down Expand Up @@ -151,19 +152,87 @@ appScenarios
},
},
},
public: {
'thing.txt': 'hello there',
},
});

addon.linkDependency('@embroider/addon-shim', { baseDir: __dirname });
addon.linkDependency('@embroider/addon-dev', { baseDir: __dirname });
addon.linkDependency('babel-plugin-ember-template-compilation', { baseDir: __dirname });
addon.linkDevDependency('@babel/core', { baseDir: __dirname });
addon.linkDevDependency('@babel/plugin-transform-class-static-block', { baseDir: __dirname });
addon.linkDevDependency('@babel/plugin-transform-class-properties', { baseDir: __dirname });
addon.linkDevDependency('@babel/plugin-proposal-decorators', { baseDir: __dirname });
addon.linkDevDependency('@rollup/plugin-babel', { baseDir: __dirname });
addon.linkDevDependency('rollup', { baseDir: __dirname });
let addonNoNamespace = baseV2Addon();
addonNoNamespace.pkg.name = 'v2-addon-no-namespace';
addonNoNamespace.pkg.scripts = {
build: 'node ./node_modules/rollup/dist/bin/rollup -c ./rollup.config.mjs',
};

merge(addonNoNamespace.files, {
src: {
components: {
'hello.hbs': '<h1>hello</h1>',
},
},
public: {
'other.txt': 'we meet again',
},
'babel.config.json': `
{
"plugins": [
"@embroider/addon-dev/template-colocation-plugin",
"@babel/plugin-transform-class-static-block",
["babel-plugin-ember-template-compilation", {
targetFormat: 'hbs',
compilerPath: 'ember-source/dist/ember-template-compiler',
}],
["@babel/plugin-proposal-decorators", { "legacy": true }],
[ "@babel/plugin-transform-class-properties" ]
]
}
`,
'rollup.config.mjs': `
import { babel } from '@rollup/plugin-babel';
import { Addon } from '@embroider/addon-dev/rollup';
const addon = new Addon({
srcDir: 'src',
destDir: 'dist',
});
export default {
output: addon.output(),
plugins: [
addon.publicEntrypoints([
'components/**/*.js',
], {
exclude: ['**/-excluded/**/*'],
}),
addon.hbs(),
addon.publicAssets('public', { namespace: '' }),
babel({ babelHelpers: 'bundled', extensions: ['.js', '.hbs', '.gjs'] }),
addon.clean(),
],
};
`,
});

function linkDependencies(addon: Project) {
addon.linkDependency('@embroider/addon-shim', { baseDir: __dirname });
addon.linkDependency('@embroider/addon-dev', { baseDir: __dirname });
addon.linkDependency('babel-plugin-ember-template-compilation', { baseDir: __dirname });
addon.linkDevDependency('@babel/core', { baseDir: __dirname });
addon.linkDevDependency('@babel/plugin-transform-class-static-block', { baseDir: __dirname });
addon.linkDevDependency('@babel/plugin-transform-class-properties', { baseDir: __dirname });
addon.linkDevDependency('@babel/plugin-proposal-decorators', { baseDir: __dirname });
addon.linkDevDependency('@rollup/plugin-babel', { baseDir: __dirname });
addon.linkDevDependency('rollup', { baseDir: __dirname });
}

linkDependencies(addon);
linkDependencies(addonNoNamespace);

project.addDevDependency(addon);
project.addDependency(addonNoNamespace);

merge(project.files, {
tests: {
Expand Down Expand Up @@ -226,6 +295,7 @@ appScenarios
if (result.exitCode !== 0) {
throw new Error(result.output);
}
await inDependency(app, 'v2-addon-no-namespace').execute('pnpm build');
});

hooks.beforeEach(assert => {
Expand Down Expand Up @@ -301,6 +371,17 @@ setComponentTemplate(
export { SingleFileComponent as default };
//# sourceMappingURL=single-file-component.js.map`);
});

test('publicAssets are namespaced correctly', async function (assert) {
let expectNoNamespaceFile = expectFilesAt(inDependency(app, 'v2-addon-no-namespace').dir, { qunit: assert });

expectFile('package.json').json('ember-addon.public-assets').deepEquals({
'./public/thing.txt': '/v2-addon/public/thing.txt',
});
expectNoNamespaceFile('package.json').json('ember-addon.public-assets').deepEquals({
'./public/other.txt': '/public/other.txt',
});
});
});

Qmodule('Consuming app', function () {
Expand Down

0 comments on commit 5acd254

Please sign in to comment.