babel-plugin-saykit 0.8.0 → 0.9.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{catalogue-B3HA3aVz.cjs → catalogue-CrZhNHS_.cjs} +0 -21
- package/dist/index.cjs +3 -4
- package/dist/index.d.cts +4 -2
- package/dist/metro/index.cjs +0 -22
- package/dist/metro/transformer.cjs +1 -15
- package/dist/next/index.cjs +1 -17
- package/dist/next/loader.cjs +1 -15
- package/package.json +6 -3
|
@@ -2,30 +2,9 @@ let node_path = require("node:path");
|
|
|
2
2
|
let node_fs = require("node:fs");
|
|
3
3
|
let _saykit_config_features_catalogue = require("@saykit/config/features/catalogue");
|
|
4
4
|
//#region src/catalogue.ts
|
|
5
|
-
/** Normalise an absolute path into the form bucket globs are written against. */
|
|
6
5
|
const toId = (path) => (0, node_path.relative)(process.cwd(), path).replaceAll("\\", "/").split("?")[0];
|
|
7
|
-
/**
|
|
8
|
-
* The glob a bucket's catalogues match, e.g. `src/locales/*.po` — the `output`
|
|
9
|
-
* template with its placeholders filled in. Bundlers that select files by glob
|
|
10
|
-
* rather than by predicate need this to target exactly the catalogues, and
|
|
11
|
-
* nothing else sharing their extension.
|
|
12
|
-
*/
|
|
13
6
|
const catalogueGlob = (bucket) => String(bucket.output).replace("{locale}", "*").replace("{extension}", bucket.formatter.extension.slice(1)).replaceAll("\\", "/").replace(/^\.\//, "");
|
|
14
|
-
/** Whether `path` is one of the config's catalogue outputs. */
|
|
15
7
|
const isCatalogue = (config, path) => config.buckets.some((bucket) => bucket.output.match(toId(path)));
|
|
16
|
-
/**
|
|
17
|
-
* Assemble the catalogue at `path` into a `{ id: string }` record, merging in
|
|
18
|
-
* the fallback chain (configured fallbacks + the source locale) so an
|
|
19
|
-
* untranslated key resolves to a fallback string rather than going missing.
|
|
20
|
-
*
|
|
21
|
-
* Returns `undefined` when the path is not a catalogue, and otherwise reports
|
|
22
|
-
* the files that fed the record alongside it — a bundler that can track them
|
|
23
|
-
* gets invalidation for free when a fallback locale is edited.
|
|
24
|
-
*
|
|
25
|
-
* Reads are synchronous so every caller can share one implementation: Babel's
|
|
26
|
-
* visitor cannot await, and the handful of files in a fallback chain are not
|
|
27
|
-
* worth an async path in a bundler that is blocked on the result anyway.
|
|
28
|
-
*/
|
|
29
8
|
function loadCatalogue(config, path) {
|
|
30
9
|
const id = toId(path);
|
|
31
10
|
const bucket = config.buckets.find((b) => b.output.match(id));
|
package/dist/index.cjs
CHANGED
|
@@ -1,9 +1,8 @@
|
|
|
1
|
-
const require_catalogue = require("./catalogue-
|
|
1
|
+
const require_catalogue = require("./catalogue-CrZhNHS_.cjs");
|
|
2
2
|
let node_path = require("node:path");
|
|
3
|
-
let _babel_core = require("@babel/core");
|
|
4
3
|
let _saykit_config_features_loader = require("@saykit/config/features/loader");
|
|
5
4
|
//#region src/index.ts
|
|
6
|
-
var src_default = (
|
|
5
|
+
var src_default = ({ types: t }, { catalogues = "inline" } = {}) => {
|
|
7
6
|
const config = (0, _saykit_config_features_loader.resolveConfig)();
|
|
8
7
|
return {
|
|
9
8
|
name: "saykit",
|
|
@@ -16,7 +15,7 @@ var src_default = (_, { catalogues = "inline" } = {}) => {
|
|
|
16
15
|
if (!catalogue) return;
|
|
17
16
|
const [specifier, ...rest] = path.node.specifiers;
|
|
18
17
|
if (specifier?.type !== "ImportDefaultSpecifier" || rest.length > 0) throw path.buildCodeFrameError("SayKit inline imports require a single default import");
|
|
19
|
-
path.replaceWith(
|
|
18
|
+
path.replaceWith(t.variableDeclaration("const", [t.variableDeclarator(t.identifier(specifier.local.name), t.objectExpression(Object.entries(catalogue.record).map(([key, value]) => t.objectProperty(t.stringLiteral(key), t.stringLiteral(value)))))]));
|
|
20
19
|
} },
|
|
21
20
|
parserOverride(code, opts, parse) {
|
|
22
21
|
const id_ = opts.sourceFileName;
|
package/dist/index.d.cts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { PluginObj, parse } from "@babel/core";
|
|
1
|
+
import { ConfigAPI, PluginObj, parse, types } from "@babel/core";
|
|
2
2
|
//#region src/index.d.ts
|
|
3
3
|
declare module '@babel/core' {
|
|
4
4
|
interface PluginObj {
|
|
@@ -21,6 +21,8 @@ interface Options {
|
|
|
21
21
|
*/
|
|
22
22
|
catalogues?: 'inline' | 'module';
|
|
23
23
|
}
|
|
24
|
-
declare const _default: (
|
|
24
|
+
declare const _default: ({ types: t }: ConfigAPI & {
|
|
25
|
+
types: typeof types;
|
|
26
|
+
}, { catalogues }?: Options) => PluginObj;
|
|
25
27
|
//#endregion
|
|
26
28
|
export { Options, _default as default };
|
package/dist/metro/index.cjs
CHANGED
|
@@ -3,13 +3,6 @@ let node_path = require("node:path");
|
|
|
3
3
|
let _saykit_config_features_loader = require("@saykit/config/features/loader");
|
|
4
4
|
let node_module = require("node:module");
|
|
5
5
|
//#region src/metro/index.ts
|
|
6
|
-
/**
|
|
7
|
-
* Resolve Metro's own transformer from the project rather than from this
|
|
8
|
-
* package, since it is the project that depends on Metro.
|
|
9
|
-
*
|
|
10
|
-
* The base is the config's `projectRoot` — `process.cwd()` is wrong whenever
|
|
11
|
-
* Metro is started from elsewhere, which in a monorepo is the normal case.
|
|
12
|
-
*/
|
|
13
6
|
const transformerPath = (0, node_path.join)(__dirname, "transformer.cjs");
|
|
14
7
|
function resolveUpstream(specifier, projectRoot) {
|
|
15
8
|
if ((0, node_path.isAbsolute)(specifier)) return specifier;
|
|
@@ -19,21 +12,6 @@ function resolveUpstream(specifier, projectRoot) {
|
|
|
19
12
|
return require.resolve(specifier);
|
|
20
13
|
}
|
|
21
14
|
}
|
|
22
|
-
/**
|
|
23
|
-
* Wrap a Metro config so SayKit catalogues load as real modules.
|
|
24
|
-
*
|
|
25
|
-
* ```js
|
|
26
|
-
* const { withSayKit } = require('babel-plugin-saykit/metro');
|
|
27
|
-
* module.exports = withSayKit(getDefaultConfig(__dirname));
|
|
28
|
-
* ```
|
|
29
|
-
*
|
|
30
|
-
* Metro's transform cache is keyed on each file's own bytes, so a catalogue has
|
|
31
|
-
* to stay a module of its own to be invalidated at all — see
|
|
32
|
-
* `./transformer.ts`.
|
|
33
|
-
*
|
|
34
|
-
* Apply this outermost. Anything wrapped around it that also sets
|
|
35
|
-
* `transformerPath` replaces this one, and catalogues stop being assembled.
|
|
36
|
-
*/
|
|
37
15
|
function withSayKit(metroConfig) {
|
|
38
16
|
if (metroConfig.transformerPath === transformerPath) return metroConfig;
|
|
39
17
|
const extensions = (0, _saykit_config_features_loader.resolveConfig)().buckets.map((bucket) => bucket.formatter.extension.slice(1)).filter((extension) => extension !== "json");
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
2
|
-
const require_catalogue = require("../catalogue-
|
|
2
|
+
const require_catalogue = require("../catalogue-CrZhNHS_.cjs");
|
|
3
3
|
let node_path = require("node:path");
|
|
4
4
|
let _saykit_config_features_loader = require("@saykit/config/features/loader");
|
|
5
5
|
let node_fs = require("node:fs");
|
|
@@ -7,21 +7,7 @@ let node_crypto = require("node:crypto");
|
|
|
7
7
|
//#region src/metro/transformer.ts
|
|
8
8
|
const config = (0, _saykit_config_features_loader.resolveConfig)();
|
|
9
9
|
const upstream = (transformerConfig) => require(transformerConfig.saykitTransformerPath);
|
|
10
|
-
/**
|
|
11
|
-
* What a catalogue transforms into depends on the SayKit config — the fallback
|
|
12
|
-
* chain it resolves, the formatter that parses it — and on the version of this
|
|
13
|
-
* package doing the assembling. Neither is a byte of the file Metro hashes, so
|
|
14
|
-
* without them in the cache key, editing `saykit.config.*` or upgrading leaves
|
|
15
|
-
* every catalogue serving the record it was cached with.
|
|
16
|
-
*/
|
|
17
10
|
const salt = (0, node_crypto.createHash)("sha1").update((0, node_fs.readFileSync)((0, node_path.join)(__dirname, "..", "..", "package.json"), "utf8")).update((0, node_fs.readFileSync)((0, _saykit_config_features_loader.resolveConfigFile)(), "utf8")).digest("hex");
|
|
18
|
-
/**
|
|
19
|
-
* Metro reads `.json` straight through `transformJSON` and never runs Babel over
|
|
20
|
-
* it, so a Babel plugin cannot reach a catalogue at all. Wrapping the transform
|
|
21
|
-
* worker is the one place that can: it substitutes the assembled record for the
|
|
22
|
-
* catalogue's own source, leaving the file a real module whose sha1 — and
|
|
23
|
-
* therefore Metro's transform cache entry — moves whenever it is edited.
|
|
24
|
-
*/
|
|
25
11
|
function transform(transformerConfig, projectRoot, filename, data, options) {
|
|
26
12
|
const worker = upstream(transformerConfig);
|
|
27
13
|
const catalogue = require_catalogue.loadCatalogue(config, filename);
|
package/dist/next/index.cjs
CHANGED
|
@@ -1,24 +1,8 @@
|
|
|
1
1
|
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
2
|
-
const require_catalogue = require("../catalogue-
|
|
2
|
+
const require_catalogue = require("../catalogue-CrZhNHS_.cjs");
|
|
3
3
|
let _saykit_config_features_loader = require("@saykit/config/features/loader");
|
|
4
4
|
//#region src/next/index.ts
|
|
5
5
|
const loader = "babel-plugin-saykit/next/loader";
|
|
6
|
-
/**
|
|
7
|
-
* Wrap a Next config so SayKit catalogues load as real modules.
|
|
8
|
-
*
|
|
9
|
-
* ```js
|
|
10
|
-
* import { withSayKit } from 'babel-plugin-saykit/next';
|
|
11
|
-
* export default withSayKit({});
|
|
12
|
-
* ```
|
|
13
|
-
*
|
|
14
|
-
* Pair it with `catalogues: 'module'` on the Babel plugin — the plugin has to
|
|
15
|
-
* leave the import alone for the loader to ever be asked for the module.
|
|
16
|
-
*
|
|
17
|
-
* Rules are derived from the SayKit config, so both bundlers get one per bucket
|
|
18
|
-
* targeting exactly that bucket's `output` — nothing else sharing the extension
|
|
19
|
-
* goes through the loader, which matters most for a `.json` bucket, where the
|
|
20
|
-
* alternative would be routing every JSON import in the app through it.
|
|
21
|
-
*/
|
|
22
6
|
function withSayKit(nextConfig = {}) {
|
|
23
7
|
const config = (0, _saykit_config_features_loader.resolveConfig)();
|
|
24
8
|
const rules = Object.fromEntries(config.buckets.map((bucket) => [`**/${require_catalogue.catalogueGlob(bucket)}`, {
|
package/dist/next/loader.cjs
CHANGED
|
@@ -1,20 +1,6 @@
|
|
|
1
|
-
const require_catalogue = require("../catalogue-
|
|
1
|
+
const require_catalogue = require("../catalogue-CrZhNHS_.cjs");
|
|
2
2
|
//#region src/next/loader.ts
|
|
3
3
|
const config = (0, require("@saykit/config/features/loader").resolveConfig)();
|
|
4
|
-
/**
|
|
5
|
-
* Replaces a catalogue file with its assembled record.
|
|
6
|
-
*
|
|
7
|
-
* This is a *loader* rather than a plugin because Turbopack runs loaders and
|
|
8
|
-
* not webpack plugins, and it is published only so `withSayKit` can name it in
|
|
9
|
-
* the rules it generates. A plain webpack, Vite or Rollup build should reach for
|
|
10
|
-
* `unplugin-saykit` instead, which does the same job through each bundler's own
|
|
11
|
-
* plugin API.
|
|
12
|
-
*
|
|
13
|
-
* The catalogue stays a real module, which is the whole point: the importer
|
|
14
|
-
* keeps a dependency edge to it, so editing a catalogue invalidates exactly the
|
|
15
|
-
* modules that read it. Inlining the record into the importer instead leaves the
|
|
16
|
-
* importer's own bytes unchanged, and no bundler can invalidate on that.
|
|
17
|
-
*/
|
|
18
4
|
function saykitLoader(source) {
|
|
19
5
|
const catalogue = require_catalogue.loadCatalogue(config, this.resourcePath);
|
|
20
6
|
if (!catalogue) return source;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "babel-plugin-saykit",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.9.0",
|
|
4
4
|
"description": "Babel plugin for SayKit",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"i18n",
|
|
@@ -48,12 +48,15 @@
|
|
|
48
48
|
"provenance": true
|
|
49
49
|
},
|
|
50
50
|
"dependencies": {
|
|
51
|
-
"@
|
|
52
|
-
"@saykit/config": "^0.8.0"
|
|
51
|
+
"@saykit/config": "^0.9.0"
|
|
53
52
|
},
|
|
54
53
|
"devDependencies": {
|
|
54
|
+
"@babel/core": "^7.29.7",
|
|
55
55
|
"@types/babel__core": "^7.20.5"
|
|
56
56
|
},
|
|
57
|
+
"peerDependencies": {
|
|
58
|
+
"@babel/core": "^7.0.0 || ^8.0.0"
|
|
59
|
+
},
|
|
57
60
|
"scripts": {
|
|
58
61
|
"check": "tsc --noEmit",
|
|
59
62
|
"build": "tsdown"
|