@knighted/jsx 1.6.3-rc.1 → 1.6.3
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/cjs/loader/jsx.cjs +27 -2
- package/dist/cjs/loader/jsx.d.cts +2 -0
- package/dist/loader/jsx.d.ts +2 -0
- package/dist/loader/jsx.js +27 -2
- package/package.json +5 -5
package/dist/cjs/loader/jsx.cjs
CHANGED
|
@@ -224,6 +224,8 @@ const TEMPLATE_PARSER_OPTIONS = {
|
|
|
224
224
|
};
|
|
225
225
|
const DEFAULT_TAGS = ['jsx', 'reactJsx'];
|
|
226
226
|
const DEFAULT_MODE = 'runtime';
|
|
227
|
+
const WEB_TARGETS = new Set(['web', 'webworker', 'electron-renderer', 'node-webkit']);
|
|
228
|
+
const isWebTarget = (target) => target ? WEB_TARGETS.has(target) : false;
|
|
227
229
|
const HELPER_SNIPPETS = {
|
|
228
230
|
react: `const __jsxReactMergeProps = (...sources) => Object.assign({}, ...sources)
|
|
229
231
|
const __jsxReact = (type, props, ...children) => React.createElement(type, props, ...children)
|
|
@@ -671,7 +673,14 @@ const transformSource = (source, config, options) => {
|
|
|
671
673
|
.filter(Boolean)
|
|
672
674
|
.join('\n');
|
|
673
675
|
if (helperSource) {
|
|
674
|
-
|
|
676
|
+
const helperBlock = `${helperSource.trimEnd()}\n\n`;
|
|
677
|
+
const shebangIndex = source.startsWith('#!') ? source.indexOf('\n') : -1;
|
|
678
|
+
if (shebangIndex >= 0) {
|
|
679
|
+
magic.appendLeft(shebangIndex + 1, helperBlock);
|
|
680
|
+
}
|
|
681
|
+
else {
|
|
682
|
+
magic.prepend(helperBlock);
|
|
683
|
+
}
|
|
675
684
|
mutated = true;
|
|
676
685
|
}
|
|
677
686
|
const code = mutated ? magic.toString() : source;
|
|
@@ -692,6 +701,8 @@ function jsxLoader(input) {
|
|
|
692
701
|
const callback = this.async();
|
|
693
702
|
try {
|
|
694
703
|
const options = this.getOptions?.() ?? {};
|
|
704
|
+
const warn = this.emitWarning?.bind(this);
|
|
705
|
+
const webTarget = isWebTarget(this.target);
|
|
695
706
|
const explicitTags = Array.isArray(options.tags)
|
|
696
707
|
? options.tags.filter((value) => typeof value === 'string' && value.length > 0)
|
|
697
708
|
: null;
|
|
@@ -705,6 +716,9 @@ function jsxLoader(input) {
|
|
|
705
716
|
const configuredTagModes = options.tagModes && typeof options.tagModes === 'object'
|
|
706
717
|
? options.tagModes
|
|
707
718
|
: undefined;
|
|
719
|
+
const userSpecifiedMode = parseLoaderMode(options.mode);
|
|
720
|
+
const defaultMode = userSpecifiedMode ?? DEFAULT_MODE;
|
|
721
|
+
const userConfiguredTags = new Set();
|
|
708
722
|
if (configuredTagModes) {
|
|
709
723
|
Object.entries(configuredTagModes).forEach(([tagName, mode]) => {
|
|
710
724
|
const parsed = parseLoaderMode(mode);
|
|
@@ -712,15 +726,26 @@ function jsxLoader(input) {
|
|
|
712
726
|
return;
|
|
713
727
|
}
|
|
714
728
|
tagModes.set(tagName, parsed);
|
|
729
|
+
userConfiguredTags.add(tagName);
|
|
715
730
|
});
|
|
716
731
|
}
|
|
717
|
-
const defaultMode = parseLoaderMode(options.mode) ?? DEFAULT_MODE;
|
|
718
732
|
const tags = Array.from(new Set([...tagList, ...tagModes.keys()]));
|
|
719
733
|
tags.forEach(tagName => {
|
|
720
734
|
if (!tagModes.has(tagName)) {
|
|
721
735
|
tagModes.set(tagName, defaultMode);
|
|
722
736
|
}
|
|
723
737
|
});
|
|
738
|
+
/**
|
|
739
|
+
* If targeting the web and runtime mode is only implied (not explicitly requested),
|
|
740
|
+
* keep the runtime output but surface a warning so users can opt into react mode when
|
|
741
|
+
* bundling for the browser.
|
|
742
|
+
*/
|
|
743
|
+
if (webTarget && userSpecifiedMode === null) {
|
|
744
|
+
const hasImplicitRuntime = tags.some(tagName => tagModes.get(tagName) === 'runtime' && !userConfiguredTags.has(tagName));
|
|
745
|
+
if (hasImplicitRuntime) {
|
|
746
|
+
warn?.(new Error('[jsx-loader] Web target detected while defaulting to runtime mode; the shipped parser expects a Node-like environment. Set mode: "react" (or configure per-tag) when bundling client code, or provide a browser-safe runtime parser if you intentionally need runtime output.'));
|
|
747
|
+
}
|
|
748
|
+
}
|
|
724
749
|
const source = typeof input === 'string' ? input : input.toString('utf8');
|
|
725
750
|
const enableSourceMap = options.sourceMap === true;
|
|
726
751
|
const { code, map } = transformSource(source, {
|
|
@@ -2,6 +2,8 @@ import { type SourceMap } from 'magic-string';
|
|
|
2
2
|
type LoaderCallback = (error: Error | null, content?: string, map?: SourceMap | null) => void;
|
|
3
3
|
type LoaderContext<TOptions> = {
|
|
4
4
|
resourcePath: string;
|
|
5
|
+
target?: string;
|
|
6
|
+
emitWarning?: (warning: Error | string) => void;
|
|
5
7
|
async(): LoaderCallback;
|
|
6
8
|
getOptions?: () => Partial<TOptions>;
|
|
7
9
|
};
|
package/dist/loader/jsx.d.ts
CHANGED
|
@@ -2,6 +2,8 @@ import { type SourceMap } from 'magic-string';
|
|
|
2
2
|
type LoaderCallback = (error: Error | null, content?: string, map?: SourceMap | null) => void;
|
|
3
3
|
type LoaderContext<TOptions> = {
|
|
4
4
|
resourcePath: string;
|
|
5
|
+
target?: string;
|
|
6
|
+
emitWarning?: (warning: Error | string) => void;
|
|
5
7
|
async(): LoaderCallback;
|
|
6
8
|
getOptions?: () => Partial<TOptions>;
|
|
7
9
|
};
|
package/dist/loader/jsx.js
CHANGED
|
@@ -218,6 +218,8 @@ const TEMPLATE_PARSER_OPTIONS = {
|
|
|
218
218
|
};
|
|
219
219
|
const DEFAULT_TAGS = ['jsx', 'reactJsx'];
|
|
220
220
|
const DEFAULT_MODE = 'runtime';
|
|
221
|
+
const WEB_TARGETS = new Set(['web', 'webworker', 'electron-renderer', 'node-webkit']);
|
|
222
|
+
const isWebTarget = (target) => target ? WEB_TARGETS.has(target) : false;
|
|
221
223
|
const HELPER_SNIPPETS = {
|
|
222
224
|
react: `const __jsxReactMergeProps = (...sources) => Object.assign({}, ...sources)
|
|
223
225
|
const __jsxReact = (type, props, ...children) => React.createElement(type, props, ...children)
|
|
@@ -665,7 +667,14 @@ const transformSource = (source, config, options) => {
|
|
|
665
667
|
.filter(Boolean)
|
|
666
668
|
.join('\n');
|
|
667
669
|
if (helperSource) {
|
|
668
|
-
|
|
670
|
+
const helperBlock = `${helperSource.trimEnd()}\n\n`;
|
|
671
|
+
const shebangIndex = source.startsWith('#!') ? source.indexOf('\n') : -1;
|
|
672
|
+
if (shebangIndex >= 0) {
|
|
673
|
+
magic.appendLeft(shebangIndex + 1, helperBlock);
|
|
674
|
+
}
|
|
675
|
+
else {
|
|
676
|
+
magic.prepend(helperBlock);
|
|
677
|
+
}
|
|
669
678
|
mutated = true;
|
|
670
679
|
}
|
|
671
680
|
const code = mutated ? magic.toString() : source;
|
|
@@ -686,6 +695,8 @@ export default function jsxLoader(input) {
|
|
|
686
695
|
const callback = this.async();
|
|
687
696
|
try {
|
|
688
697
|
const options = this.getOptions?.() ?? {};
|
|
698
|
+
const warn = this.emitWarning?.bind(this);
|
|
699
|
+
const webTarget = isWebTarget(this.target);
|
|
689
700
|
const explicitTags = Array.isArray(options.tags)
|
|
690
701
|
? options.tags.filter((value) => typeof value === 'string' && value.length > 0)
|
|
691
702
|
: null;
|
|
@@ -699,6 +710,9 @@ export default function jsxLoader(input) {
|
|
|
699
710
|
const configuredTagModes = options.tagModes && typeof options.tagModes === 'object'
|
|
700
711
|
? options.tagModes
|
|
701
712
|
: undefined;
|
|
713
|
+
const userSpecifiedMode = parseLoaderMode(options.mode);
|
|
714
|
+
const defaultMode = userSpecifiedMode ?? DEFAULT_MODE;
|
|
715
|
+
const userConfiguredTags = new Set();
|
|
702
716
|
if (configuredTagModes) {
|
|
703
717
|
Object.entries(configuredTagModes).forEach(([tagName, mode]) => {
|
|
704
718
|
const parsed = parseLoaderMode(mode);
|
|
@@ -706,15 +720,26 @@ export default function jsxLoader(input) {
|
|
|
706
720
|
return;
|
|
707
721
|
}
|
|
708
722
|
tagModes.set(tagName, parsed);
|
|
723
|
+
userConfiguredTags.add(tagName);
|
|
709
724
|
});
|
|
710
725
|
}
|
|
711
|
-
const defaultMode = parseLoaderMode(options.mode) ?? DEFAULT_MODE;
|
|
712
726
|
const tags = Array.from(new Set([...tagList, ...tagModes.keys()]));
|
|
713
727
|
tags.forEach(tagName => {
|
|
714
728
|
if (!tagModes.has(tagName)) {
|
|
715
729
|
tagModes.set(tagName, defaultMode);
|
|
716
730
|
}
|
|
717
731
|
});
|
|
732
|
+
/**
|
|
733
|
+
* If targeting the web and runtime mode is only implied (not explicitly requested),
|
|
734
|
+
* keep the runtime output but surface a warning so users can opt into react mode when
|
|
735
|
+
* bundling for the browser.
|
|
736
|
+
*/
|
|
737
|
+
if (webTarget && userSpecifiedMode === null) {
|
|
738
|
+
const hasImplicitRuntime = tags.some(tagName => tagModes.get(tagName) === 'runtime' && !userConfiguredTags.has(tagName));
|
|
739
|
+
if (hasImplicitRuntime) {
|
|
740
|
+
warn?.(new Error('[jsx-loader] Web target detected while defaulting to runtime mode; the shipped parser expects a Node-like environment. Set mode: "react" (or configure per-tag) when bundling client code, or provide a browser-safe runtime parser if you intentionally need runtime output.'));
|
|
741
|
+
}
|
|
742
|
+
}
|
|
718
743
|
const source = typeof input === 'string' ? input : input.toString('utf8');
|
|
719
744
|
const enableSourceMap = options.sourceMap === true;
|
|
720
745
|
const { code, map } = transformSource(source, {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@knighted/jsx",
|
|
3
|
-
"version": "1.6.3
|
|
3
|
+
"version": "1.6.3",
|
|
4
4
|
"description": "Runtime JSX tagged template that renders DOM or React trees anywhere without a build step.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"jsx runtime",
|
|
@@ -119,9 +119,9 @@
|
|
|
119
119
|
"check-types:lib": "tsc --noEmit --project tsconfig.json",
|
|
120
120
|
"check-types:demo": "tsc --noEmit --project examples/browser/tsconfig.json",
|
|
121
121
|
"check-types:test": "tsc --noEmit --project tsconfig.vitest.json",
|
|
122
|
-
"clean:deps": "rimraf
|
|
123
|
-
"clean:dist": "rimraf
|
|
124
|
-
"clean": "npm run clean:
|
|
122
|
+
"clean:deps": "rimraf node_modules",
|
|
123
|
+
"clean:dist": "rimraf dist",
|
|
124
|
+
"clean": "npm run clean:dist && npm run clean:deps",
|
|
125
125
|
"lint": "eslint src test",
|
|
126
126
|
"pretest": "npm run build",
|
|
127
127
|
"cycles": "madge src --circular --extensions ts,tsx,js,jsx --ts-config tsconfig.json",
|
|
@@ -143,7 +143,7 @@
|
|
|
143
143
|
},
|
|
144
144
|
"devDependencies": {
|
|
145
145
|
"@eslint/js": "^9.39.1",
|
|
146
|
-
"@knighted/duel": "^4.0.0
|
|
146
|
+
"@knighted/duel": "^4.0.0",
|
|
147
147
|
"@oxc-project/types": "^0.105.0",
|
|
148
148
|
"@playwright/test": "^1.57.0",
|
|
149
149
|
"@rspack/core": "^1.0.5",
|