babel-preset-exodra 0.1.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/README.md ADDED
@@ -0,0 +1,120 @@
1
+ # babel-preset-exodra
2
+
3
+ Babel preset that compiles Exodra JSX in one line — JSX syntax (with namespaced
4
+ `bind:` / `cache:` directives), the [`@exodra/babel-plugin-jsx`](../babel-plugin-jsx)
5
+ transform, and `@babel/preset-typescript` for `.ts`/`.tsx`.
6
+
7
+ ## Installation
8
+
9
+ ```bash
10
+ npm install --save-dev babel-preset-exodra
11
+ ```
12
+
13
+ ## Usage
14
+
15
+ ```javascript
16
+ // babel.config.js
17
+ module.exports = {
18
+ presets: ['exodra'],
19
+ };
20
+ ```
21
+
22
+ ### Options
23
+
24
+ ```javascript
25
+ // babel.config.js
26
+ module.exports = {
27
+ presets: [
28
+ ['exodra', {
29
+ importSource: '@exodra/core', // where auto-imported h/text come from
30
+ hoistStatic: true, // compile-time clone-cache for static subtrees
31
+ typescript: true, // include preset-typescript (turn off if TS is handled elsewhere)
32
+ }],
33
+ ],
34
+ };
35
+ ```
36
+
37
+ ## Testing with Jest
38
+
39
+ This preset is what makes Exodra component tests runnable under Jest. Jest **can**
40
+ compile Exodra JSX — through `babel-jest` (Jest's default Babel transform), which
41
+ picks up `babel.config.js` automatically. `ts-jest` and `@swc/jest` do **not** run
42
+ Babel plugins and so cannot compile Exodra JSX.
43
+
44
+ ```javascript
45
+ // babel.config.js
46
+ module.exports = { presets: ['exodra'] };
47
+ ```
48
+
49
+ That is all Jest needs — component tests then compile the same way Vite compiles
50
+ them.
51
+
52
+ > If Jest reports an unexpected token on `<`, or "namespace tags are not
53
+ > supported" on `bind:value`, you are almost certainly on `ts-jest` / `@swc/jest`.
54
+ > Switch the transform to `babel-jest` and add the preset above.
55
+
56
+ ## Other bundlers & runners
57
+
58
+ Exodra JSX is compiled by a **Babel** plugin, so any tool that can run Babel can
59
+ compile it — via this preset. Tools that do **not** run Babel plugins (esbuild,
60
+ SWC, Bun's native transpiler) need a dedicated plugin that hands the file to
61
+ Babel; those wrap this same preset, so every path compiles identically.
62
+
63
+ | Tool | How | Package |
64
+ | --- | --- | --- |
65
+ | **Vite / Vitest** | plugin | [`@exodra/vite-plugin`](../vite-plugin-exodra) |
66
+ | **Jest** | `babel-jest` + this preset | `babel-preset-exodra` |
67
+ | **esbuild / tsup** | plugin | [`esbuild-plugin-exodra`](../esbuild-plugin-exodra) |
68
+ | **Rollup** | plugin | [`rollup-plugin-exodra`](../rollup-plugin-exodra) |
69
+ | **Bun** | plugin | [`bun-plugin-exodra`](../bun-plugin-exodra) |
70
+ | **webpack** | `babel-loader` + this preset | *(no package — see below)* |
71
+ | **Parcel** | `.babelrc` + this preset | *(no package — see below)* |
72
+ | **SWC / Next.js / `swc-loader`** | native Wasm plugin (full parity) | [`swc-plugin-exodra`](../swc-plugin-exodra) |
73
+
74
+ ### webpack
75
+
76
+ ```javascript
77
+ // webpack.config.js
78
+ module.exports = {
79
+ module: {
80
+ rules: [
81
+ {
82
+ test: /\.[jt]sx$/,
83
+ use: {
84
+ loader: 'babel-loader',
85
+ options: { presets: ['exodra'] },
86
+ },
87
+ },
88
+ ],
89
+ },
90
+ resolve: { extensions: ['.js', '.jsx', '.ts', '.tsx'] },
91
+ };
92
+ ```
93
+
94
+ ### Parcel
95
+
96
+ Parcel reads Babel config automatically:
97
+
98
+ ```json
99
+ // .babelrc
100
+ { "presets": ["exodra"] }
101
+ ```
102
+
103
+ ### SWC / Next.js (default), `@swc/jest`
104
+
105
+ SWC does not run Babel plugins, so this preset cannot drive it. Use the native
106
+ Wasm plugin [`swc-plugin-exodra`](../swc-plugin-exodra) instead — a full-parity
107
+ port (buckets, children, `bind:`/`cache:` directives, fragments, static hoisting,
108
+ shadow-safe imports, strict errors).
109
+
110
+ ## Programmatic runner
111
+
112
+ Every bundler plugin above calls one shared function, exported here, so there is a
113
+ single copy of the pipeline **and** its invocation:
114
+
115
+ ```javascript
116
+ import { transformExodraJsx } from 'babel-preset-exodra';
117
+
118
+ const result = await transformExodraJsx(sourceCode, '/abs/path/File.tsx');
119
+ // -> { code, map } | null (typescript defaults on for .tsx, off otherwise)
120
+ ```
package/dist/index.cjs ADDED
@@ -0,0 +1,111 @@
1
+ "use strict";
2
+ // The canonical Exodra Babel integration, in one place.
3
+ //
4
+ // - `default` export: a Babel PRESET that bundles the full pipeline (JSX syntax
5
+ // with `throwIfNamespace: false` so `bind:`/`cache:` survive, the
6
+ // `@exodra/babel-plugin-jsx` transform, and preset-typescript). This is the
7
+ // Jest / babel.config.js entry point:
8
+ //
9
+ // // babel.config.js
10
+ // module.exports = { presets: ['exodra'] };
11
+ //
12
+ // - `transformExodraJsx(code, filename)`: a small imperative RUNNER that applies
13
+ // that preset via `@babel/core`. It is the single source of truth every
14
+ // bundler plugin (Vite / esbuild / Rollup / Bun) calls, so there is exactly
15
+ // ONE copy of the pipeline AND its invocation — no drift between how tools
16
+ // compile Exodra JSX.
17
+ //
18
+ // ts-jest / @swc/jest do NOT run Babel plugins and so cannot compile Exodra JSX —
19
+ // use `babel-jest` with the preset.
20
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
21
+ if (k2 === undefined) k2 = k;
22
+ var desc = Object.getOwnPropertyDescriptor(m, k);
23
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
24
+ desc = { enumerable: true, get: function() { return m[k]; } };
25
+ }
26
+ Object.defineProperty(o, k2, desc);
27
+ }) : (function(o, m, k, k2) {
28
+ if (k2 === undefined) k2 = k;
29
+ o[k2] = m[k];
30
+ }));
31
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
32
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
33
+ }) : function(o, v) {
34
+ o["default"] = v;
35
+ });
36
+ var __importStar = (this && this.__importStar) || (function () {
37
+ var ownKeys = function(o) {
38
+ ownKeys = Object.getOwnPropertyNames || function (o) {
39
+ var ar = [];
40
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
41
+ return ar;
42
+ };
43
+ return ownKeys(o);
44
+ };
45
+ return function (mod) {
46
+ if (mod && mod.__esModule) return mod;
47
+ var result = {};
48
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
49
+ __setModuleDefault(result, mod);
50
+ return result;
51
+ };
52
+ })();
53
+ Object.defineProperty(exports, "__esModule", { value: true });
54
+ exports.transformExodraJsx = transformExodraJsx;
55
+ const babel = __importStar(require("@babel/core"));
56
+ // @babel/plugin-syntax-jsx and @babel/preset-typescript ship no type
57
+ // declarations, and @exodra/babel-plugin-jsx ships as CommonJS with an empty
58
+ // `export {}` .d.ts — so pull all three runtime values via require.
59
+ /* eslint-disable @typescript-eslint/no-var-requires */
60
+ const syntaxJsx = require('@babel/plugin-syntax-jsx');
61
+ const presetTypescript = require('@babel/preset-typescript');
62
+ const exodraJsxPlugin = require('@exodra/babel-plugin-jsx');
63
+ function babelPresetExodra(api, options = {}) {
64
+ api.assertVersion(7);
65
+ const { importSource = '@exodra/core', hoistStatic = true, typescript = true, mode = 'dom', } = options;
66
+ const presets = [];
67
+ if (typescript) {
68
+ presets.push([
69
+ presetTypescript,
70
+ { isTSX: true, allExtensions: true },
71
+ ]);
72
+ }
73
+ return {
74
+ presets,
75
+ plugins: [
76
+ // Parse JSX; keep namespaced directives (`bind:value`, `cache:key`)
77
+ // instead of throwing, so the Exodra plugin can lower them.
78
+ [syntaxJsx, { throwIfNamespace: false }],
79
+ [exodraJsxPlugin, { importSource, hoistStatic, mode }],
80
+ ],
81
+ };
82
+ }
83
+ exports.default = babelPresetExodra;
84
+ /**
85
+ * Compile one Exodra JSX/TSX source through the preset. The single invocation
86
+ * every bundler plugin shares. Returns `null` when Babel emits nothing.
87
+ */
88
+ async function transformExodraJsx(code, filename, options = {}) {
89
+ const typescript = options.typescript ?? filename.endsWith('.tsx');
90
+ const result = await babel.transformAsync(code, {
91
+ filename,
92
+ babelrc: false,
93
+ configFile: false,
94
+ sourceMaps: true,
95
+ presets: [
96
+ [
97
+ babelPresetExodra,
98
+ {
99
+ typescript,
100
+ importSource: options.importSource,
101
+ hoistStatic: options.hoistStatic,
102
+ mode: options.mode,
103
+ },
104
+ ],
105
+ ],
106
+ });
107
+ if (!result || result.code == null)
108
+ return null;
109
+ return { code: result.code, map: result.map ?? null };
110
+ }
111
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1,46 @@
1
+ import type { ConfigAPI, PluginItem } from '@babel/core';
2
+ export interface ExodraPresetOptions {
3
+ /** Module the auto-imported `h`/`text` come from. Default `@exodra/core`. */
4
+ importSource?: string;
5
+ /** Compile-time clone-cache for static subtrees. Default `true`. */
6
+ hoistStatic?: boolean;
7
+ /**
8
+ * Include `@babel/preset-typescript` so `.ts`/`.tsx` sources are stripped of
9
+ * types. Default `true` — turn off if your pipeline already handles TS.
10
+ */
11
+ typescript?: boolean;
12
+ /**
13
+ * 'dom' (default) compiles JSX to h() schemas for the client renderer; 'ssr'
14
+ * compiles to HTML-string functions for the server (see @exodra/babel-plugin-jsx).
15
+ */
16
+ mode?: 'dom' | 'ssr';
17
+ }
18
+ declare function babelPresetExodra(api: ConfigAPI, options?: ExodraPresetOptions): {
19
+ presets: PluginItem[];
20
+ plugins: PluginItem[];
21
+ };
22
+ export default babelPresetExodra;
23
+ /** Result of {@link transformExodraJsx}: emitted code plus a raw source map. */
24
+ export interface ExodraTransformResult {
25
+ code: string;
26
+ /** Babel's raw source map object; cast to your bundler's map input type. */
27
+ map: object | null;
28
+ }
29
+ /** Options for {@link transformExodraJsx}, forwarded to the preset. */
30
+ export interface ExodraTransformOptions {
31
+ importSource?: string;
32
+ hoistStatic?: boolean;
33
+ /**
34
+ * Run preset-typescript. Defaults to `true` for `.tsx` files and `false`
35
+ * otherwise (a `.jsx` file has no types and must not be parsed as TSX).
36
+ */
37
+ typescript?: boolean;
38
+ /** 'dom' (default) or 'ssr' — see ExodraPresetOptions.mode. */
39
+ mode?: 'dom' | 'ssr';
40
+ }
41
+ /**
42
+ * Compile one Exodra JSX/TSX source through the preset. The single invocation
43
+ * every bundler plugin shares. Returns `null` when Babel emits nothing.
44
+ */
45
+ export declare function transformExodraJsx(code: string, filename: string, options?: ExodraTransformOptions): Promise<ExodraTransformResult | null>;
46
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAoBA,OAAO,KAAK,EAAE,SAAS,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAWzD,MAAM,WAAW,mBAAmB;IAChC,6EAA6E;IAC7E,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,oEAAoE;IACpE,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB;;;OAGG;IACH,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB;;;OAGG;IACH,IAAI,CAAC,EAAE,KAAK,GAAG,KAAK,CAAC;CACxB;AAED,iBAAS,iBAAiB,CACtB,GAAG,EAAE,SAAS,EACd,OAAO,GAAE,mBAAwB,GAClC;IAAE,OAAO,EAAE,UAAU,EAAE,CAAC;IAAC,OAAO,EAAE,UAAU,EAAE,CAAA;CAAE,CA2BlD;AAED,eAAe,iBAAiB,CAAC;AAEjC,gFAAgF;AAChF,MAAM,WAAW,qBAAqB;IAClC,IAAI,EAAE,MAAM,CAAC;IACb,4EAA4E;IAC5E,GAAG,EAAE,MAAM,GAAG,IAAI,CAAC;CACtB;AAED,uEAAuE;AACvE,MAAM,WAAW,sBAAsB;IACnC,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB;;;OAGG;IACH,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,+DAA+D;IAC/D,IAAI,CAAC,EAAE,KAAK,GAAG,KAAK,CAAC;CACxB;AAED;;;GAGG;AACH,wBAAsB,kBAAkB,CACpC,IAAI,EAAE,MAAM,EACZ,QAAQ,EAAE,MAAM,EAChB,OAAO,GAAE,sBAA2B,GACrC,OAAO,CAAC,qBAAqB,GAAG,IAAI,CAAC,CAuBvC"}
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AAAA,wDAAwD;AACxD,EAAE;AACF,iFAAiF;AACjF,qEAAqE;AACrE,+EAA+E;AAC/E,yCAAyC;AACzC,EAAE;AACF,0BAA0B;AAC1B,iDAAiD;AACjD,EAAE;AACF,kFAAkF;AAClF,2EAA2E;AAC3E,+EAA+E;AAC/E,8EAA8E;AAC9E,yBAAyB;AACzB,EAAE;AACF,kFAAkF;AAClF,oCAAoC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAyFpC,gDA2BC;AAlHD,mDAAqC;AAGrC,qEAAqE;AACrE,6EAA6E;AAC7E,oEAAoE;AACpE,uDAAuD;AACvD,MAAM,SAAS,GAAG,OAAO,CAAC,0BAA0B,CAAe,CAAC;AACpE,MAAM,gBAAgB,GAAG,OAAO,CAAC,0BAA0B,CAAe,CAAC;AAC3E,MAAM,eAAe,GAAG,OAAO,CAAC,0BAA0B,CAAe,CAAC;AAoB1E,SAAS,iBAAiB,CACtB,GAAc,EACd,UAA+B,EAAE;IAEjC,GAAG,CAAC,aAAa,CAAC,CAAC,CAAC,CAAC;IAErB,MAAM,EACF,YAAY,GAAG,cAAc,EAC7B,WAAW,GAAG,IAAI,EAClB,UAAU,GAAG,IAAI,EACjB,IAAI,GAAG,KAAK,GACf,GAAG,OAAO,CAAC;IAEZ,MAAM,OAAO,GAAiB,EAAE,CAAC;IACjC,IAAI,UAAU,EAAE,CAAC;QACb,OAAO,CAAC,IAAI,CAAC;YACT,gBAAgB;YAChB,EAAE,KAAK,EAAE,IAAI,EAAE,aAAa,EAAE,IAAI,EAAE;SACvC,CAAC,CAAC;IACP,CAAC;IAED,OAAO;QACH,OAAO;QACP,OAAO,EAAE;YACL,oEAAoE;YACpE,4DAA4D;YAC5D,CAAC,SAAS,EAAE,EAAE,gBAAgB,EAAE,KAAK,EAAE,CAAC;YACxC,CAAC,eAAe,EAAE,EAAE,YAAY,EAAE,WAAW,EAAE,IAAI,EAAE,CAAC;SACzD;KACJ,CAAC;AACN,CAAC;AAED,kBAAe,iBAAiB,CAAC;AAsBjC;;;GAGG;AACI,KAAK,UAAU,kBAAkB,CACpC,IAAY,EACZ,QAAgB,EAChB,UAAkC,EAAE;IAEpC,MAAM,UAAU,GAAG,OAAO,CAAC,UAAU,IAAI,QAAQ,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC;IAEnE,MAAM,MAAM,GAAG,MAAM,KAAK,CAAC,cAAc,CAAC,IAAI,EAAE;QAC5C,QAAQ;QACR,OAAO,EAAE,KAAK;QACd,UAAU,EAAE,KAAK;QACjB,UAAU,EAAE,IAAI;QAChB,OAAO,EAAE;YACL;gBACI,iBAA+B;gBAC/B;oBACI,UAAU;oBACV,YAAY,EAAE,OAAO,CAAC,YAAY;oBAClC,WAAW,EAAE,OAAO,CAAC,WAAW;oBAChC,IAAI,EAAE,OAAO,CAAC,IAAI;iBACrB;aACJ;SACJ;KACJ,CAAC,CAAC;IAEH,IAAI,CAAC,MAAM,IAAI,MAAM,CAAC,IAAI,IAAI,IAAI;QAAE,OAAO,IAAI,CAAC;IAChD,OAAO,EAAE,IAAI,EAAE,MAAM,CAAC,IAAI,EAAE,GAAG,EAAG,MAAM,CAAC,GAAqB,IAAI,IAAI,EAAE,CAAC;AAC7E,CAAC"}
package/package.json ADDED
@@ -0,0 +1,47 @@
1
+ {
2
+ "name": "babel-preset-exodra",
3
+ "version": "0.1.0",
4
+ "description": "Babel preset for Exodra: JSX + TypeScript + directives, ready for Jest/babel-jest",
5
+ "keywords": [
6
+ "exodra",
7
+ "babel",
8
+ "babel-preset",
9
+ "jsx",
10
+ "jest",
11
+ "babel-jest",
12
+ "typescript"
13
+ ],
14
+ "main": "dist/index.cjs",
15
+ "types": "dist/index.d.ts",
16
+ "files": [
17
+ "dist"
18
+ ],
19
+ "publishConfig": {
20
+ "access": "public"
21
+ },
22
+ "scripts": {
23
+ "build": "tsc && mv dist/index.js dist/index.cjs",
24
+ "prepublishOnly": "npm run build",
25
+ "test": "vitest run"
26
+ },
27
+ "author": "Andrei Baikov",
28
+ "license": "MIT",
29
+ "homepage": "https://exodra.org",
30
+ "repository": {
31
+ "type": "git",
32
+ "url": "git+https://github.com/abaikov/exodra.git",
33
+ "directory": "packages/babel-preset-exodra"
34
+ },
35
+ "bugs": {
36
+ "url": "https://github.com/abaikov/exodra/issues"
37
+ },
38
+ "dependencies": {
39
+ "@babel/core": "^7.24.0",
40
+ "@babel/plugin-syntax-jsx": "^7.24.0",
41
+ "@babel/preset-typescript": "^7.24.0",
42
+ "@exodra/babel-plugin-jsx": "^0.1.0"
43
+ },
44
+ "devDependencies": {
45
+ "@types/babel__core": "^7.20.5"
46
+ }
47
+ }