@tsrx/turbopack-plugin-react 0.1.88 → 0.1.90

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,49 @@
1
+ # @tsrx/turbopack-plugin-react
2
+
3
+ Turbopack integration for compiling `@tsrx/react` `.tsrx` files in Next.js.
4
+
5
+ ## Installation
6
+
7
+ ```bash
8
+ pnpm add @tsrx/react react react-dom
9
+ pnpm add -D @tsrx/turbopack-plugin-react next
10
+ ```
11
+
12
+ ## Usage
13
+
14
+ ```ts
15
+ import tsrxReactTurbopack from '@tsrx/turbopack-plugin-react';
16
+
17
+ export default tsrxReactTurbopack({
18
+ reactStrictMode: true,
19
+ });
20
+ ```
21
+
22
+ The helper installs Turbopack rules that compile `.tsrx` modules with
23
+ `@tsrx/react` and return the result as `*.tsx` so Next's React pipeline can finish
24
+ the JSX transform. Sibling-scoped `<style>` blocks (each styles its siblings and
25
+ everything below them) are emitted through a sibling `?tsrx-css&lang.css` import
26
+ and handed back to Turbopack as a CSS module.
27
+
28
+ It also adds `.tsrx` to `turbopack.resolveExtensions`.
29
+
30
+ ## Options
31
+
32
+ Pass Next.js config as the first argument. The second argument is optional:
33
+
34
+ - `runtimeImports`: helper import mode (`'compiler'` by default, or `'direct'` for
35
+ standalone runtime imports).
36
+
37
+ ```ts
38
+ export default tsrxReactTurbopack({}, { runtimeImports: 'direct' });
39
+ ```
40
+
41
+ When using `runtimeImports: 'direct'`, install the runtime as a direct production
42
+ dependency of the package that owns the compiled modules:
43
+
44
+ ```bash
45
+ pnpm add @tsrx/react-runtime
46
+ ```
47
+
48
+ The helper only emits bare `@tsrx/react-runtime/*` imports and does not provide
49
+ the runtime package.
package/package.json CHANGED
@@ -3,7 +3,7 @@
3
3
  "description": "Turbopack integration for @tsrx/react",
4
4
  "license": "MIT",
5
5
  "author": "Dominic Gannaway",
6
- "version": "0.1.88",
6
+ "version": "0.1.90",
7
7
  "type": "module",
8
8
  "publishConfig": {
9
9
  "access": "public"
@@ -20,7 +20,7 @@
20
20
  }
21
21
  },
22
22
  "dependencies": {
23
- "@tsrx/react": "0.2.65"
23
+ "@tsrx/react": "0.2.67"
24
24
  },
25
25
  "peerDependencies": {
26
26
  "next": ">=15.3.0"
package/src/css-loader.js CHANGED
@@ -13,7 +13,7 @@ import { compile } from '@tsrx/react';
13
13
  /**
14
14
  * Re-runs the `@tsrx/react` compiler against the `.tsrx` source to extract
15
15
  * the scoped CSS emitted by its `<style>` block. Invoked when Turbopack
16
- * resolves the sibling `?tsrx-css&lang.css` import prepended by the JS loader.
16
+ * resolves the sibling `?tsrx-css&lang.css` import emitted by the JS loader.
17
17
  *
18
18
  * @this {LoaderContext}
19
19
  * @param {string} source
package/src/loader.js CHANGED
@@ -5,97 +5,18 @@ import { compile } from '@tsrx/react';
5
5
  const CSS_QUERY = '?tsrx-css&lang.css';
6
6
 
7
7
  /**
8
- * @param {string} source
9
- * @param {number} index
10
- * @returns {number}
11
- */
12
- function skip_whitespace_and_comments(source, index) {
13
- while (index < source.length) {
14
- const char = source[index];
15
- if (char === ' ' || char === '\t' || char === '\n' || char === '\r') {
16
- index++;
17
- continue;
18
- }
19
- if (char === '/' && source[index + 1] === '/') {
20
- index += 2;
21
- while (index < source.length && source[index] !== '\n') {
22
- index++;
23
- }
24
- continue;
25
- }
26
- if (char === '/' && source[index + 1] === '*') {
27
- index += 2;
28
- while (index < source.length && !(source[index] === '*' && source[index + 1] === '/')) {
29
- index++;
30
- }
31
- index = Math.min(index + 2, source.length);
32
- continue;
33
- }
34
- break;
35
- }
36
- return index;
37
- }
38
-
39
- /**
40
- * @param {string} source
41
- * @param {number} index
42
- * @returns {number}
43
- */
44
- function read_directive_statement(source, index) {
45
- const quote = source[index];
46
- if (quote !== '"' && quote !== "'") {
47
- return -1;
48
- }
49
-
50
- let cursor = index + 1;
51
- let value = '';
52
- while (cursor < source.length) {
53
- const char = source[cursor];
54
- if (char === '\\') {
55
- value += source.slice(cursor, cursor + 2);
56
- cursor += 2;
57
- continue;
58
- }
59
- if (char === quote) {
60
- cursor++;
61
- break;
62
- }
63
- value += char;
64
- cursor++;
65
- }
66
-
67
- if (cursor > source.length || !value.startsWith('use ')) {
68
- return -1;
69
- }
70
-
71
- cursor = skip_whitespace_and_comments(source, cursor);
72
- if (source[cursor] === ';') {
73
- cursor++;
74
- }
75
- return skip_whitespace_and_comments(source, cursor);
76
- }
77
-
78
- /**
8
+ * Appends an import of the sibling virtual CSS resource. It goes after the
9
+ * module's own imports so the stylesheets of imported themes are added to the
10
+ * graph first and a rule in the applying module wins at equal specificity.
11
+ * Top-level directives such as `'use client'` stay first, and nothing above
12
+ * the import moves, so the compiler's source map still applies.
13
+ *
79
14
  * @param {string} code
80
15
  * @param {string} resource_path
81
16
  * @returns {string}
82
17
  */
83
- function prepend_css_import(code, resource_path) {
84
- const css_import = `import ${JSON.stringify(resource_path + CSS_QUERY)};\n`;
85
- const initial_index = skip_whitespace_and_comments(code, 0);
86
- let insertion_index = initial_index;
87
- let scan_index = initial_index;
88
-
89
- while (scan_index < code.length) {
90
- const next_index = read_directive_statement(code, scan_index);
91
- if (next_index === -1) {
92
- break;
93
- }
94
- insertion_index = next_index;
95
- scan_index = next_index;
96
- }
97
-
98
- return `${code.slice(0, insertion_index)}${css_import}${code.slice(insertion_index)}`;
18
+ function append_css_import(code, resource_path) {
19
+ return `${code}\nimport ${JSON.stringify(resource_path + CSS_QUERY)};\n`;
99
20
  }
100
21
 
101
22
  /**
@@ -109,7 +30,7 @@ function prepend_css_import(code, resource_path) {
109
30
  /**
110
31
  * Compile `.tsrx` files to TSX for consumption by Turbopack's built-in
111
32
  * TypeScript/React pipeline. When a component-local `<style>` block is
112
- * present, prepend an import to a sibling virtual CSS resource that is handled
33
+ * present, append an import of a sibling virtual CSS resource that is handled
113
34
  * by the Turbopack config helper's query-targeted CSS rule.
114
35
  *
115
36
  * @this {LoaderContext}
@@ -121,10 +42,9 @@ export default function tsrx_react_turbopack_loader(source) {
121
42
 
122
43
  try {
123
44
  const { code, map, css } = compile(source, this.resourcePath, this.getOptions?.());
124
- const output = css ? prepend_css_import(code, this.resourcePath) : code;
125
- const output_map = css ? null : map;
45
+ const output = css ? append_css_import(code, this.resourcePath) : code;
126
46
 
127
- callback(null, output, /** @type {any} */ (output_map ?? undefined));
47
+ callback(null, output, /** @type {any} */ (map ?? undefined));
128
48
  } catch (/** @type {any} */ err) {
129
49
  callback(err);
130
50
  }