@porotkin/vite-plugin-react-kotlinjs 0.0.5 → 0.0.7
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 +1 -1
- package/package.json +3 -2
- package/src/index.js +1 -1
- package/src/normalize-exports.js +10 -0
- package/src/refresh-runtime.js +10 -0
- package/src/refresh-wrapper.js +9 -18
- package/src/vite-babel.js +97 -11
- package/src/vite-react-refresh.js +2 -2
package/README.md
CHANGED
|
@@ -10,7 +10,7 @@ This plugin is inspired by the original
|
|
|
10
10
|
Add the following dependency to your `build.gradle.kts`:
|
|
11
11
|
```kotlin
|
|
12
12
|
dependencies {
|
|
13
|
-
jsMainImplementation(devNpm("@porotkin/vite-plugin-react-kotlinjs", "^0.0.
|
|
13
|
+
jsMainImplementation(devNpm("@porotkin/vite-plugin-react-kotlinjs", "^0.0.7"))
|
|
14
14
|
}
|
|
15
15
|
```
|
|
16
16
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@porotkin/vite-plugin-react-kotlinjs",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.7",
|
|
4
4
|
"description": "Support React fast refresh in Kotlin/JS",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"author": "Mikhail Porotkin",
|
|
@@ -21,10 +21,11 @@
|
|
|
21
21
|
"postinstall": "node copyRefreshRuntime.js"
|
|
22
22
|
},
|
|
23
23
|
"dependencies": {
|
|
24
|
+
"@babel/core": "^7.28.4",
|
|
24
25
|
"@rolldown/pluginutils": "1.0.0-beta.41",
|
|
25
26
|
"react-refresh": "^0.17.0"
|
|
26
27
|
},
|
|
27
28
|
"devDependencies": {
|
|
28
|
-
"@vitejs/plugin-react": "5.0.4"
|
|
29
|
+
"@vitejs/plugin-react": "^5.0.4"
|
|
29
30
|
}
|
|
30
31
|
}
|
package/src/index.js
CHANGED
|
@@ -16,7 +16,7 @@ export default (options) => {
|
|
|
16
16
|
|
|
17
17
|
const derivedOptions = {
|
|
18
18
|
skipFastRefresh: true,
|
|
19
|
-
|
|
19
|
+
detectComponent: (code) => code.includes('kotlin-react-core/react/ChildrenBuilder.mjs'),
|
|
20
20
|
filter,
|
|
21
21
|
...options,
|
|
22
22
|
};
|
package/src/refresh-runtime.js
CHANGED
|
@@ -661,3 +661,13 @@ export const __hmr_import = (module) => import(/* @vite-ignore */ module)
|
|
|
661
661
|
|
|
662
662
|
// For backwards compatibility with @vitejs/plugin-react.
|
|
663
663
|
export default { injectIntoGlobalHook }
|
|
664
|
+
export function normalizeExports(value) {
|
|
665
|
+
if (!value) return [];
|
|
666
|
+
const [entry] = Object.entries(value)
|
|
667
|
+
if (!entry) return [];
|
|
668
|
+
const [key, type] = entry
|
|
669
|
+
const name = key.replace("get_", "");
|
|
670
|
+
return {
|
|
671
|
+
[name]: (...args) => type?.(...args),
|
|
672
|
+
}
|
|
673
|
+
}
|
package/src/refresh-wrapper.js
CHANGED
|
@@ -1,44 +1,35 @@
|
|
|
1
1
|
export const runtimePublicPath = '/@react-refresh'
|
|
2
2
|
|
|
3
3
|
// NOTE: this is exposed publicly via plugin-react
|
|
4
|
-
export const preambleCode = `
|
|
4
|
+
export const preambleCode = `
|
|
5
|
+
import { injectIntoGlobalHook } from "${runtimePublicPath.slice(1)}";
|
|
5
6
|
injectIntoGlobalHook(window);
|
|
6
7
|
window.$RefreshReg$ = () => {};
|
|
7
|
-
window.$RefreshSig$ = () => (type) => type
|
|
8
|
+
window.$RefreshSig$ = () => (type) => type;
|
|
9
|
+
`
|
|
8
10
|
|
|
9
11
|
export const getPreambleCode = () => preambleCode
|
|
10
12
|
|
|
11
|
-
export function addRefreshWrapper(code, pluginName, id
|
|
12
|
-
const componentName = getComponentName?.(code)
|
|
13
|
-
if (!componentName) return code;
|
|
14
|
-
|
|
13
|
+
export function addRefreshWrapper(code, pluginName, id) {
|
|
15
14
|
const registerHmr = `
|
|
16
15
|
import * as RefreshRuntime from "${runtimePublicPath}";
|
|
17
16
|
const inWebWorker = typeof WorkerGlobalScope !== "undefined" && self instanceof WorkerGlobalScope;
|
|
18
17
|
if (import.meta.hot && !inWebWorker) {
|
|
19
|
-
$RefreshReg$(get_${componentName}?.(), "${componentName}")
|
|
20
18
|
RefreshRuntime.__hmr_import(import.meta.url).then((currentExports) => {
|
|
21
19
|
RefreshRuntime.registerExportsForReactRefresh(${JSON.stringify(id)}, currentExports);
|
|
22
20
|
import.meta.hot.accept((nextExports) => {
|
|
23
21
|
if (!nextExports) return;
|
|
24
|
-
const invalidateMessage = RefreshRuntime.validateRefreshBoundaryAndEnqueueUpdate(${JSON.stringify(id)}, normalizeExports(currentExports), normalizeExports(nextExports));
|
|
22
|
+
const invalidateMessage = RefreshRuntime.validateRefreshBoundaryAndEnqueueUpdate(${JSON.stringify(id)}, RefreshRuntime.normalizeExports(currentExports), RefreshRuntime.normalizeExports(nextExports));
|
|
25
23
|
if (invalidateMessage) import.meta.hot.invalidate(invalidateMessage);
|
|
26
24
|
});
|
|
27
25
|
});
|
|
28
26
|
}
|
|
29
|
-
function normalizeExports(value) {
|
|
30
|
-
if (!value) return [];
|
|
31
|
-
const [entry] = Object.entries(value)
|
|
32
|
-
if (!entry) return [];
|
|
33
|
-
const [key, type] = entry
|
|
34
|
-
const name = key.replace("get_", "");
|
|
35
|
-
return {
|
|
36
|
-
[name]: (...args) => type?.(...args),
|
|
37
|
-
}
|
|
38
|
-
}
|
|
39
27
|
function $RefreshReg$(type, id) {
|
|
40
28
|
return RefreshRuntime.register(type, ${JSON.stringify(id)} + " " + id);
|
|
41
29
|
}
|
|
30
|
+
function $RefreshSig$() {
|
|
31
|
+
return RefreshRuntime.createSignatureFunctionForTransform();
|
|
32
|
+
}
|
|
42
33
|
`
|
|
43
34
|
return code + registerHmr;
|
|
44
35
|
}
|
package/src/vite-babel.js
CHANGED
|
@@ -1,24 +1,110 @@
|
|
|
1
1
|
import {addRefreshWrapper} from "./refresh-wrapper.js";
|
|
2
2
|
|
|
3
|
+
let babel;
|
|
4
|
+
|
|
5
|
+
async function loadBabel() {
|
|
6
|
+
if (!babel) babel = await import("@babel/core");
|
|
7
|
+
return babel;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
let isProduction = true;
|
|
11
|
+
let projectRoot = process.cwd();
|
|
12
|
+
let runPluginOverrides;
|
|
13
|
+
|
|
14
|
+
function canSkipBabel(plugins, babelOptions) {
|
|
15
|
+
return !(plugins.length || babelOptions.presets.length || babelOptions.configFile || babelOptions.babelrc);
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
const loadedPlugin = /* @__PURE__ */ new Map();
|
|
19
|
+
|
|
20
|
+
function loadPlugin(path) {
|
|
21
|
+
const cached = loadedPlugin.get(path);
|
|
22
|
+
if (cached) return cached;
|
|
23
|
+
const promise = import(path).then((module) => {
|
|
24
|
+
const value = module.default || module;
|
|
25
|
+
loadedPlugin.set(path, value);
|
|
26
|
+
return value;
|
|
27
|
+
});
|
|
28
|
+
loadedPlugin.set(path, promise);
|
|
29
|
+
return promise;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
function createBabelOptions(rawOptions) {
|
|
33
|
+
const babelOptions = {
|
|
34
|
+
babelrc: false,
|
|
35
|
+
configFile: false,
|
|
36
|
+
...rawOptions
|
|
37
|
+
};
|
|
38
|
+
babelOptions.plugins ||= [];
|
|
39
|
+
babelOptions.presets ||= [];
|
|
40
|
+
babelOptions.overrides ||= [];
|
|
41
|
+
babelOptions.parserOpts ||= {};
|
|
42
|
+
babelOptions.parserOpts.plugins ||= [];
|
|
43
|
+
return babelOptions;
|
|
44
|
+
}
|
|
45
|
+
|
|
3
46
|
export const viteBabelPlugin = (mainOptions) => ({
|
|
4
47
|
name: "vite:react-plugin-kotlinjs",
|
|
5
48
|
enforce: "pre",
|
|
6
49
|
configResolved(config) {
|
|
7
|
-
|
|
50
|
+
projectRoot = config.root;
|
|
51
|
+
isProduction = config.isProduction;
|
|
52
|
+
mainOptions.skipFastRefresh = isProduction || config.command === "build" || config.server.hmr === false;
|
|
53
|
+
const hooks = config.plugins.map((plugin) => plugin.api?.reactBabel).filter(function (value) {
|
|
54
|
+
return value !== void 0;
|
|
55
|
+
});
|
|
56
|
+
if (hooks.length > 0) runPluginOverrides = (babelOptions, context) => {
|
|
57
|
+
hooks.forEach((hook) => hook(babelOptions, context, config));
|
|
58
|
+
};
|
|
8
59
|
},
|
|
9
60
|
transform: {
|
|
10
|
-
async handler(code, id) {
|
|
61
|
+
async handler(code, id, options) {
|
|
11
62
|
const [filepath] = id.split("?");
|
|
12
|
-
if (!mainOptions?.filter(filepath) || !mainOptions?.
|
|
63
|
+
if (!mainOptions?.filter(filepath) || !mainOptions?.detectComponent(code)) return;
|
|
64
|
+
const ssr = options?.ssr === true;
|
|
65
|
+
const babelOptions = (() => {
|
|
66
|
+
const newBabelOptions = createBabelOptions({});
|
|
67
|
+
runPluginOverrides?.(newBabelOptions, {
|
|
68
|
+
id,
|
|
69
|
+
ssr
|
|
70
|
+
});
|
|
71
|
+
return newBabelOptions;
|
|
72
|
+
})();
|
|
73
|
+
const plugins = [...babelOptions.plugins];
|
|
13
74
|
const useFastRefresh = !mainOptions.skipFastRefresh;
|
|
14
|
-
if (
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
75
|
+
if (useFastRefresh) plugins.push([await loadPlugin("react-refresh/babel"), {skipEnvCheck: true}]);
|
|
76
|
+
if (canSkipBabel(plugins, babelOptions)) return;
|
|
77
|
+
const parserPlugins = [...babelOptions.parserOpts.plugins];
|
|
78
|
+
const result = await (await loadBabel()).transformAsync(code, {
|
|
79
|
+
...babelOptions,
|
|
80
|
+
root: projectRoot,
|
|
81
|
+
filename: id,
|
|
82
|
+
sourceFileName: filepath,
|
|
83
|
+
retainLines: !isProduction,
|
|
84
|
+
parserOpts: {
|
|
85
|
+
...babelOptions.parserOpts,
|
|
86
|
+
sourceType: "module",
|
|
87
|
+
allowAwaitOutsideFunction: true,
|
|
88
|
+
plugins: parserPlugins
|
|
89
|
+
},
|
|
90
|
+
generatorOpts: {
|
|
91
|
+
...babelOptions.generatorOpts,
|
|
92
|
+
importAttributesKeyword: "with",
|
|
93
|
+
decoratorsBeforeExport: true
|
|
94
|
+
},
|
|
95
|
+
plugins,
|
|
96
|
+
sourceMaps: true
|
|
97
|
+
});
|
|
98
|
+
if (result) {
|
|
99
|
+
if (!useFastRefresh) return {
|
|
100
|
+
code: result.code,
|
|
101
|
+
map: result.map
|
|
102
|
+
};
|
|
103
|
+
return {
|
|
104
|
+
code: addRefreshWrapper(result.code, "vite:react-plugin-kotlinjs", id),
|
|
105
|
+
map: result.map
|
|
106
|
+
};
|
|
107
|
+
}
|
|
22
108
|
}
|
|
23
109
|
}
|
|
24
110
|
})
|
|
@@ -2,7 +2,7 @@ import {dirname, join} from 'node:path'
|
|
|
2
2
|
import {fileURLToPath} from 'node:url'
|
|
3
3
|
import {exactRegex} from '@rolldown/pluginutils'
|
|
4
4
|
import {readFileSync} from 'node:fs'
|
|
5
|
-
import {runtimePublicPath} from "./refresh-wrapper.js";
|
|
5
|
+
import {getPreambleCode, runtimePublicPath} from "./refresh-wrapper.js";
|
|
6
6
|
import {silenceUseClientWarning} from "./warning.js";
|
|
7
7
|
|
|
8
8
|
const _dirname = dirname(fileURLToPath(import.meta.url))
|
|
@@ -13,7 +13,7 @@ const dependencies = [
|
|
|
13
13
|
]
|
|
14
14
|
|
|
15
15
|
export const viteReactRefreshPlugin = (options) => ({
|
|
16
|
-
name: 'vite:react-refresh',
|
|
16
|
+
name: 'vite:react-refresh-kotlinjs',
|
|
17
17
|
enforce: 'pre',
|
|
18
18
|
config: (userConfig) => ({
|
|
19
19
|
build: silenceUseClientWarning(userConfig),
|