Skip to content

Publish the transforms as babel-plugin-ember-formatjs - #24

Draft
aklkv wants to merge 14 commits into
mainmatter:mainfrom
aklkv:feat/babel-plugin-package
Draft

aklkv wants to merge 14 commits into
mainmatter:mainfrom
aklkv:feat/babel-plugin-package

Conversation

@aklkv

@aklkv aklkv commented Oct 20, 2026

Copy link
Copy Markdown
Contributor

Closes #15. Last part of splitting up #16. Draft because it builds on the earlier PRs, #17 to #23. Only the last 2 commits are new here.

Vite apps can't use the transforms without a classic addon in their build. The transforms move unchanged into babel-plugin-ember-formatjs, which has no Ember dependencies. ember-formatjs keeps the classic wiring and depends on it, so classic apps don't need to change anything. The README shows the Vite setup.

babel-plugin-ember-formatjs is unclaimed on npm, so the first publish makes the NPM_TOKEN account its owner. It starts at 0.1.3 so both packages release together.

aklkv added 2 commits October 20, 2026 03:45
It had no tests. These run it through
babel-plugin-ember-template-compilation v2, which is what
ember-cli-htmlbars uses, and pin down how it rewrites and which modules
it treats as the app's.
babel-plugin-ember-template-compilation v4, which Embroider uses, sets
neither env.meta.moduleName nor env.moduleName, only env.filename, so
every template threw. Check all three, keeping the old precedence for
the path that feeds the id pattern, so classic output is unchanged.

The template tests now run against v4 as well as v2.
aklkv added 12 commits October 22, 2026 01:34
The replacer assigned arguments[1] and arguments[2] by index, so a call
with no values printed as intl.t('key', ). The fixtures didn't catch it
because babel-plugin-tester runs the output through prettier, which
drops the trailing comma, so the new tests read babel's own output.
Under Embroider + Vite, ember-intl's own source goes through the app's
babel pass. Its internal intl.formatMessage(descriptor, values) was
rewritten to intl.t('[sha512:contenthash:base64:6]', values), with the
raw id pattern as the key.

The replacer now fires only when the first argument is an object
literal with defaultMessage or id. Neither transform touches files under
node_modules any more, apart from an app old Embroider stages there,
since libraries ship already compiled.
Nothing tested index.js. These stand the addon up with a stub host and
check the htmlbars registry entry, the parallel-babel descriptor
ember-cli rebuilds the plugin from in workers, option merging, and that
the babel plugin is added once.
ember-cli-htmlbars passes baseDir() to hash-for-dep to build its cache
key, and expects the plugin's own package (its own plugins use
__dirname). path.resolve('./') is the app's root, so every build hashed
the app's whole dependency graph instead.
eslint 8 is end of life and babel-plugin-tester was on a canary. eslint
10 rejects the /* eslint-env */ comment in template-plugin.js; the flat
config already gives every file node globals.
release-plan 0.20 needs Node 22 or later, so the release workflows move
off Node 18, which the engines field doesn't allow anyway.
3.x hasn't had a release since March 2025 and only accepts TypeScript 5.

4 is ESM-only, and the plugins require() it from CommonJS, which works
without a flag from Node 20.19.0 and 22.12.0. That drops Node 20.0-20.18
and 22.0-22.11 from the engines range.

The fixtures pass unchanged, so translation keys stay the same.
The plugin asserted Babel 7, so Babel 8 refused to load it. Nothing else
needed changing: the suite passes on @babel/core 8.0.5 unchanged, which
the next commit makes CI check.
The suite now runs on @babel/core 8 across Node 22, 24 and 26. Babel 8
needs Node 22, so another job runs Node 20.19.0, the engines floor, on
Babel 7. It overrides @babel/core everywhere and fails if any copy of
Babel 8 is left. Lint moves to Node 24 with the rest of the dev tooling.
ember-formatjs moves to packages/ember-formatjs, unchanged, as the only
package. The root becomes a private package holding the lint, test and
release tooling, and runs each package's tests.

The package lists what it publishes in "files" instead of relying on
.npmignore, which let 0.1.3 ship its tests and the repo's config. It
carries its own LICENSE, since npm only packs the one next to
package.json, and copies the root README in when it's packed, so the
npm page keeps the full docs.
An Embroider + Vite app can't use the transforms without putting a
classic addon in its build, since they only ship inside ember-formatjs.

They move, unchanged, into a new babel-plugin-ember-formatjs package
with no Ember dependencies, which a Vite app wires into its Babel
config. ember-formatjs keeps the classic wiring and depends on it, so
classic apps install the same one package as before.

The transform tests move with the transforms; the addon keeps the
tests for its own wiring.
Explain the two packages, show what to add to the babel.config.mjs an
app already has and how to pass options to both transforms, and fix the
example key, which is the one for 'Hello!' rather than 'Hello'.
@aklkv
aklkv force-pushed the feat/babel-plugin-package branch from d920f78 to e611a3a Compare October 22, 2026 08:37
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Using plugins without the classic addon

1 participant