@knighted/jsx 1.5.2 → 1.6.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 +1 -0
- package/dist/cjs/debug/diagnostics.cjs +57 -0
- package/dist/cjs/debug/diagnostics.d.cts +6 -0
- package/dist/cjs/debug/index.cjs +7 -0
- package/dist/cjs/debug/index.d.cts +2 -0
- package/dist/cjs/internal/attribute-resolution.cjs +22 -4
- package/dist/cjs/internal/attribute-resolution.d.cts +5 -0
- package/dist/cjs/internal/dev-environment.cjs +41 -0
- package/dist/cjs/internal/dev-environment.d.cts +4 -0
- package/dist/cjs/internal/event-bindings.cjs +11 -2
- package/dist/cjs/internal/event-bindings.d.cts +5 -1
- package/dist/cjs/internal/template-diagnostics.cjs +171 -0
- package/dist/cjs/internal/template-diagnostics.d.cts +13 -0
- package/dist/cjs/jsx.cjs +2 -2
- package/dist/cjs/loader/jsx.cjs +72 -20
- package/dist/cjs/loader/jsx.d.cts +6 -1
- package/dist/cjs/node/debug/index.cjs +6 -0
- package/dist/cjs/node/debug/index.d.cts +2 -0
- package/dist/cjs/react/react-jsx.cjs +1 -1
- package/dist/cjs/runtime/shared.cjs +41 -22
- package/dist/cjs/runtime/shared.d.cts +5 -2
- package/dist/debug/diagnostics.d.ts +6 -0
- package/dist/debug/diagnostics.js +52 -0
- package/dist/debug/index.d.ts +2 -0
- package/dist/debug/index.js +3 -0
- package/dist/internal/attribute-resolution.d.ts +5 -0
- package/dist/internal/attribute-resolution.js +20 -3
- package/dist/internal/dev-environment.d.ts +4 -0
- package/dist/internal/dev-environment.js +34 -0
- package/dist/internal/event-bindings.d.ts +5 -1
- package/dist/internal/event-bindings.js +9 -1
- package/dist/internal/template-diagnostics.d.ts +13 -0
- package/dist/internal/template-diagnostics.js +167 -0
- package/dist/jsx.js +3 -3
- package/dist/lite/debug/diagnostics.js +1 -0
- package/dist/lite/debug/index.js +8 -0
- package/dist/lite/index.js +8 -4
- package/dist/lite/node/debug/index.js +8 -0
- package/dist/lite/node/index.js +8 -4
- package/dist/lite/node/react/index.js +7 -3
- package/dist/lite/react/index.js +7 -3
- package/dist/loader/jsx.d.ts +6 -1
- package/dist/loader/jsx.js +72 -20
- package/dist/node/debug/index.d.ts +2 -0
- package/dist/node/debug/index.js +6 -0
- package/dist/react/react-jsx.js +2 -2
- package/dist/runtime/shared.d.ts +5 -2
- package/dist/runtime/shared.js +39 -21
- package/package.json +39 -7
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import { enableJsxDebugDiagnostics } from '../../debug/diagnostics.cjs';
|
|
2
|
+
import { ensureNodeDom } from '../bootstrap.cjs';
|
|
3
|
+
import { jsx as baseJsx } from '../../jsx.cjs';
|
|
4
|
+
enableJsxDebugDiagnostics({ mode: 'always' });
|
|
5
|
+
ensureNodeDom();
|
|
6
|
+
export const jsx = baseJsx;
|
|
@@ -127,7 +127,7 @@ const reactJsx = (templates, ...values) => {
|
|
|
127
127
|
const build = (0, shared_js_1.buildTemplate)(templates, values);
|
|
128
128
|
const result = (0, oxc_parser_1.parseSync)('inline.jsx', build.source, shared_js_1.parserOptions);
|
|
129
129
|
if (result.errors.length > 0) {
|
|
130
|
-
throw new Error((0, shared_js_1.
|
|
130
|
+
throw new Error((0, shared_js_1.formatTaggedTemplateParserError)('reactJsx', templates, build.diagnostics, result.errors[0]));
|
|
131
131
|
}
|
|
132
132
|
const root = (0, shared_js_1.extractRootNode)(result.program);
|
|
133
133
|
const ctx = {
|
|
@@ -1,31 +1,34 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.buildTemplate = exports.ensureBinding = exports.sanitizeIdentifier = exports.evaluateExpression = exports.collectPlaceholderNames = exports.normalizeJsxTextSegments = exports.walkAst = exports.getIdentifierName = exports.extractRootNode = exports.
|
|
3
|
+
exports.buildTemplate = exports.ensureBinding = exports.sanitizeIdentifier = exports.evaluateExpression = exports.collectPlaceholderNames = exports.normalizeJsxTextSegments = exports.walkAst = exports.getIdentifierName = exports.extractRootNode = exports.parserOptions = exports.formatParserError = exports.placeholderPattern = exports.PLACEHOLDER_PREFIX = exports.formatTaggedTemplateParserError = void 0;
|
|
4
|
+
var template_diagnostics_js_1 = require("../internal/template-diagnostics.cjs");
|
|
5
|
+
Object.defineProperty(exports, "formatTaggedTemplateParserError", { enumerable: true, get: function () { return template_diagnostics_js_1.formatTaggedTemplateParserError; } });
|
|
4
6
|
const OPEN_TAG_RE = /<\s*$/;
|
|
5
7
|
const CLOSE_TAG_RE = /<\/\s*$/;
|
|
6
8
|
exports.PLACEHOLDER_PREFIX = '__KX_EXPR__';
|
|
7
9
|
exports.placeholderPattern = new RegExp(`${exports.PLACEHOLDER_PREFIX}\\d+_\\d+__`, 'g');
|
|
8
10
|
let invocationCounter = 0;
|
|
9
|
-
exports.parserOptions = {
|
|
10
|
-
lang: 'jsx',
|
|
11
|
-
sourceType: 'module',
|
|
12
|
-
range: true,
|
|
13
|
-
preserveParens: true,
|
|
14
|
-
};
|
|
15
11
|
const formatParserError = (error) => {
|
|
16
12
|
let message = `[oxc-parser] ${error.message}`;
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
message += `\n${label.message}`;
|
|
21
|
-
}
|
|
13
|
+
const primaryLabel = error.labels?.[0];
|
|
14
|
+
if (primaryLabel?.message) {
|
|
15
|
+
message += `\n${primaryLabel.message}`;
|
|
22
16
|
}
|
|
23
17
|
if (error.codeframe) {
|
|
24
18
|
message += `\n${error.codeframe}`;
|
|
25
19
|
}
|
|
20
|
+
if (error.helpMessage) {
|
|
21
|
+
message += `\n${error.helpMessage}`;
|
|
22
|
+
}
|
|
26
23
|
return message;
|
|
27
24
|
};
|
|
28
25
|
exports.formatParserError = formatParserError;
|
|
26
|
+
exports.parserOptions = {
|
|
27
|
+
lang: 'jsx',
|
|
28
|
+
sourceType: 'module',
|
|
29
|
+
range: true,
|
|
30
|
+
preserveParens: true,
|
|
31
|
+
};
|
|
29
32
|
const extractRootNode = (program) => {
|
|
30
33
|
for (const statement of program.body) {
|
|
31
34
|
if (statement.type === 'ExpressionStatement') {
|
|
@@ -183,24 +186,40 @@ const buildTemplate = (strings, values) => {
|
|
|
183
186
|
let source = raw[0] ?? '';
|
|
184
187
|
const templateId = invocationCounter++;
|
|
185
188
|
let placeholderIndex = 0;
|
|
189
|
+
const expressionRanges = [];
|
|
186
190
|
for (let idx = 0; idx < values.length; idx++) {
|
|
187
191
|
const chunk = raw[idx] ?? '';
|
|
188
192
|
const nextChunk = raw[idx + 1] ?? '';
|
|
189
193
|
const value = values[idx];
|
|
190
194
|
const isTagNamePosition = OPEN_TAG_RE.test(chunk) || CLOSE_TAG_RE.test(chunk);
|
|
195
|
+
let insertion;
|
|
191
196
|
if (isTagNamePosition && typeof value === 'function') {
|
|
192
197
|
const binding = (0, exports.ensureBinding)(value, bindings, bindingLookup);
|
|
193
|
-
|
|
194
|
-
continue;
|
|
198
|
+
insertion = binding.name;
|
|
195
199
|
}
|
|
196
|
-
if (isTagNamePosition && typeof value === 'string') {
|
|
197
|
-
|
|
198
|
-
continue;
|
|
200
|
+
else if (isTagNamePosition && typeof value === 'string') {
|
|
201
|
+
insertion = value;
|
|
199
202
|
}
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
203
|
+
else {
|
|
204
|
+
const placeholder = `${exports.PLACEHOLDER_PREFIX}${templateId}_${placeholderIndex++}__`;
|
|
205
|
+
placeholders.set(placeholder, value);
|
|
206
|
+
insertion = placeholder;
|
|
207
|
+
}
|
|
208
|
+
const sourceStart = source.length;
|
|
209
|
+
source += insertion;
|
|
210
|
+
const sourceEnd = source.length;
|
|
211
|
+
expressionRanges.push({
|
|
212
|
+
index: idx,
|
|
213
|
+
sourceStart,
|
|
214
|
+
sourceEnd,
|
|
215
|
+
});
|
|
216
|
+
source += nextChunk;
|
|
217
|
+
}
|
|
218
|
+
return {
|
|
219
|
+
source,
|
|
220
|
+
placeholders,
|
|
221
|
+
bindings,
|
|
222
|
+
diagnostics: { expressionRanges },
|
|
223
|
+
};
|
|
205
224
|
};
|
|
206
225
|
exports.buildTemplate = buildTemplate;
|
|
@@ -1,7 +1,11 @@
|
|
|
1
1
|
import type { Expression, JSXElement, JSXFragment, JSXIdentifier, JSXMemberExpression, JSXNamespacedName, Program } from '@oxc-project/types';
|
|
2
2
|
import type { OxcError, ParserOptions } from 'oxc-parser';
|
|
3
|
+
import type { TemplateDiagnostics } from '../internal/template-diagnostics.cjs';
|
|
4
|
+
export { formatTaggedTemplateParserError } from '../internal/template-diagnostics.cjs';
|
|
5
|
+
export type { TemplateDiagnostics, TemplateExpressionRange, } from '../internal/template-diagnostics.cjs';
|
|
3
6
|
export declare const PLACEHOLDER_PREFIX = "__KX_EXPR__";
|
|
4
7
|
export declare const placeholderPattern: RegExp;
|
|
8
|
+
export declare const formatParserError: (error: OxcError) => string;
|
|
5
9
|
type AnyTemplateFunction = (...args: any[]) => unknown;
|
|
6
10
|
type AnyTemplateConstructor = abstract new (...args: any[]) => unknown;
|
|
7
11
|
export type TemplateComponent = (AnyTemplateFunction | AnyTemplateConstructor) & {
|
|
@@ -16,6 +20,7 @@ export type TemplateBuildResult<TComponent extends TemplateComponent> = {
|
|
|
16
20
|
source: string;
|
|
17
21
|
placeholders: Map<string, unknown>;
|
|
18
22
|
bindings: BindingEntry<TComponent>[];
|
|
23
|
+
diagnostics: TemplateDiagnostics;
|
|
19
24
|
};
|
|
20
25
|
export type TemplateContext<TComponent extends TemplateComponent> = {
|
|
21
26
|
source: string;
|
|
@@ -23,7 +28,6 @@ export type TemplateContext<TComponent extends TemplateComponent> = {
|
|
|
23
28
|
components: Map<string, TComponent>;
|
|
24
29
|
};
|
|
25
30
|
export declare const parserOptions: ParserOptions;
|
|
26
|
-
export declare const formatParserError: (error: OxcError) => string;
|
|
27
31
|
export declare const extractRootNode: (program: Program) => JSXElement | JSXFragment;
|
|
28
32
|
export declare const getIdentifierName: (identifier: JSXIdentifier | JSXNamespacedName | JSXMemberExpression) => string;
|
|
29
33
|
type AnyOxcNode = {
|
|
@@ -37,4 +41,3 @@ export declare const evaluateExpression: <TComponent extends TemplateComponent>(
|
|
|
37
41
|
export declare const sanitizeIdentifier: (value: string) => string;
|
|
38
42
|
export declare const ensureBinding: <TComponent extends TemplateComponent>(value: TComponent, bindings: BindingEntry<TComponent>[], bindingLookup: Map<TComponent, BindingEntry<TComponent>>) => BindingEntry<TComponent>;
|
|
39
43
|
export declare const buildTemplate: <TComponent extends TemplateComponent>(strings: TemplateStringsArray, values: unknown[]) => TemplateBuildResult<TComponent>;
|
|
40
|
-
export {};
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
export type JsxDiagnosticsMode = 'env' | 'always';
|
|
2
|
+
export type EnableJsxDebugDiagnosticsOptions = {
|
|
3
|
+
mode?: JsxDiagnosticsMode;
|
|
4
|
+
};
|
|
5
|
+
export declare const enableJsxDebugDiagnostics: (options?: EnableJsxDebugDiagnosticsOptions) => void;
|
|
6
|
+
export declare const disableJsxDebugDiagnostics: () => void;
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import { setAttributeDiagnosticsHooks, } from '../internal/attribute-resolution.js';
|
|
2
|
+
import { setEventDiagnosticsHooks, } from '../internal/event-bindings.js';
|
|
3
|
+
import { createDevError, describeValue, emitDevWarning, isDevEnvironment, } from '../internal/dev-environment.js';
|
|
4
|
+
const isAsciiLowercase = (char) => char >= 'a' && char <= 'z';
|
|
5
|
+
let diagnosticsMode = 'env';
|
|
6
|
+
const shouldRunDiagnostics = () => diagnosticsMode === 'always' || (diagnosticsMode === 'env' && isDevEnvironment());
|
|
7
|
+
const shouldForceWarnings = () => diagnosticsMode === 'always';
|
|
8
|
+
const attributeDiagnostics = {
|
|
9
|
+
warnLowercaseEventProp(name) {
|
|
10
|
+
if (!shouldRunDiagnostics()) {
|
|
11
|
+
return;
|
|
12
|
+
}
|
|
13
|
+
if (!name.startsWith('on') || name.startsWith('on:') || name.length < 3) {
|
|
14
|
+
return;
|
|
15
|
+
}
|
|
16
|
+
const indicator = name[2] ?? '';
|
|
17
|
+
if (!isAsciiLowercase(indicator)) {
|
|
18
|
+
return;
|
|
19
|
+
}
|
|
20
|
+
const suggestion = `${name.slice(0, 2)}${indicator.toUpperCase()}${name.slice(3)}`;
|
|
21
|
+
emitDevWarning(`Use camelCase DOM event props when targeting runtime jsx templates. Received "${name}"; did you mean "${suggestion}"?`, shouldForceWarnings());
|
|
22
|
+
},
|
|
23
|
+
ensureValidDangerouslySetInnerHTML(value) {
|
|
24
|
+
if (!shouldRunDiagnostics()) {
|
|
25
|
+
return;
|
|
26
|
+
}
|
|
27
|
+
if (!value || typeof value !== 'object' || Array.isArray(value)) {
|
|
28
|
+
throw createDevError('dangerouslySetInnerHTML expects an object with a string __html field.');
|
|
29
|
+
}
|
|
30
|
+
const html = value.__html;
|
|
31
|
+
if (typeof html !== 'string') {
|
|
32
|
+
throw createDevError(`dangerouslySetInnerHTML.__html must be a string but received ${describeValue(html)}.`);
|
|
33
|
+
}
|
|
34
|
+
},
|
|
35
|
+
};
|
|
36
|
+
const eventDiagnostics = {
|
|
37
|
+
onInvalidHandler(propName, value) {
|
|
38
|
+
if (!shouldRunDiagnostics()) {
|
|
39
|
+
return;
|
|
40
|
+
}
|
|
41
|
+
throw createDevError(`The "${propName}" prop expects a function, EventListenerObject, or descriptor ({ handler }) but received ${describeValue(value)}.`);
|
|
42
|
+
},
|
|
43
|
+
};
|
|
44
|
+
export const enableJsxDebugDiagnostics = (options) => {
|
|
45
|
+
diagnosticsMode = options?.mode ?? 'env';
|
|
46
|
+
setAttributeDiagnosticsHooks(attributeDiagnostics);
|
|
47
|
+
setEventDiagnosticsHooks(eventDiagnostics);
|
|
48
|
+
};
|
|
49
|
+
export const disableJsxDebugDiagnostics = () => {
|
|
50
|
+
setAttributeDiagnosticsHooks(null);
|
|
51
|
+
setEventDiagnosticsHooks(null);
|
|
52
|
+
};
|
|
@@ -1,5 +1,10 @@
|
|
|
1
1
|
import type { Expression, JSXAttribute, JSXElement, JSXFragment, JSXSpreadAttribute } from '@oxc-project/types';
|
|
2
2
|
import type { TemplateComponent, TemplateContext } from '../runtime/shared.js';
|
|
3
|
+
export type AttributeDiagnosticsHooks = {
|
|
4
|
+
warnLowercaseEventProp?: (name: string) => void;
|
|
5
|
+
ensureValidDangerouslySetInnerHTML?: (value: unknown) => void;
|
|
6
|
+
};
|
|
7
|
+
export declare const setAttributeDiagnosticsHooks: (hooks: AttributeDiagnosticsHooks | null) => void;
|
|
3
8
|
export type Namespace = 'svg' | null;
|
|
4
9
|
export type EvaluateExpressionWithNamespace<TComponent extends TemplateComponent> = (expression: Expression | JSXElement | JSXFragment, ctx: TemplateContext<TComponent>, namespace: Namespace) => unknown;
|
|
5
10
|
export type ResolveAttributesDependencies<TComponent extends TemplateComponent> = {
|
|
@@ -1,7 +1,23 @@
|
|
|
1
|
+
let attributeDiagnostics = null;
|
|
2
|
+
export const setAttributeDiagnosticsHooks = (hooks) => {
|
|
3
|
+
attributeDiagnostics = hooks;
|
|
4
|
+
};
|
|
5
|
+
const warnLowercaseEventProp = (name) => {
|
|
6
|
+
attributeDiagnostics?.warnLowercaseEventProp?.(name);
|
|
7
|
+
};
|
|
8
|
+
const ensureValidDangerouslySetInnerHTML = (value) => {
|
|
9
|
+
attributeDiagnostics?.ensureValidDangerouslySetInnerHTML?.(value);
|
|
10
|
+
};
|
|
1
11
|
export const createResolveAttributes = (deps) => {
|
|
2
12
|
const { getIdentifierName, evaluateExpressionWithNamespace } = deps;
|
|
3
13
|
return (attributes, ctx, namespace) => {
|
|
4
14
|
const props = {};
|
|
15
|
+
const assignProp = (propName, propValue) => {
|
|
16
|
+
if (propName === 'dangerouslySetInnerHTML') {
|
|
17
|
+
ensureValidDangerouslySetInnerHTML(propValue);
|
|
18
|
+
}
|
|
19
|
+
props[propName] = propValue;
|
|
20
|
+
};
|
|
5
21
|
attributes.forEach(attribute => {
|
|
6
22
|
if (attribute.type === 'JSXSpreadAttribute') {
|
|
7
23
|
const spreadValue = evaluateExpressionWithNamespace(attribute.argument, ctx, namespace);
|
|
@@ -13,19 +29,20 @@ export const createResolveAttributes = (deps) => {
|
|
|
13
29
|
return;
|
|
14
30
|
}
|
|
15
31
|
const name = getIdentifierName(attribute.name);
|
|
32
|
+
warnLowercaseEventProp(name);
|
|
16
33
|
if (!attribute.value) {
|
|
17
|
-
|
|
34
|
+
assignProp(name, true);
|
|
18
35
|
return;
|
|
19
36
|
}
|
|
20
37
|
if (attribute.value.type === 'Literal') {
|
|
21
|
-
|
|
38
|
+
assignProp(name, attribute.value.value);
|
|
22
39
|
return;
|
|
23
40
|
}
|
|
24
41
|
if (attribute.value.type === 'JSXExpressionContainer') {
|
|
25
42
|
if (attribute.value.expression.type === 'JSXEmptyExpression') {
|
|
26
43
|
return;
|
|
27
44
|
}
|
|
28
|
-
|
|
45
|
+
assignProp(name, evaluateExpressionWithNamespace(attribute.value.expression, ctx, namespace));
|
|
29
46
|
}
|
|
30
47
|
});
|
|
31
48
|
return props;
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
const DEV_PREFIX = '@knighted/jsx';
|
|
2
|
+
const formatDevMessage = (message) => `${DEV_PREFIX}: ${message}`;
|
|
3
|
+
export const isDevEnvironment = () => typeof process !== 'undefined' && process.env?.KNIGHTED_JSX_DEBUG === '1';
|
|
4
|
+
export const describeValue = (value) => {
|
|
5
|
+
if (value === null) {
|
|
6
|
+
return 'null';
|
|
7
|
+
}
|
|
8
|
+
if (value === undefined) {
|
|
9
|
+
return 'undefined';
|
|
10
|
+
}
|
|
11
|
+
if (typeof value === 'function') {
|
|
12
|
+
return value.name ? `function ${value.name}` : 'function';
|
|
13
|
+
}
|
|
14
|
+
if (Array.isArray(value)) {
|
|
15
|
+
return 'array';
|
|
16
|
+
}
|
|
17
|
+
if (typeof value === 'object') {
|
|
18
|
+
const ctor = value.constructor;
|
|
19
|
+
if (ctor && typeof ctor.name === 'string' && ctor.name && ctor.name !== 'Object') {
|
|
20
|
+
return `${ctor.name} instance`;
|
|
21
|
+
}
|
|
22
|
+
return 'object';
|
|
23
|
+
}
|
|
24
|
+
return typeof value;
|
|
25
|
+
};
|
|
26
|
+
export const createDevError = (message) => new Error(formatDevMessage(message));
|
|
27
|
+
export const emitDevWarning = (message, force = false) => {
|
|
28
|
+
if (!force && !isDevEnvironment()) {
|
|
29
|
+
return;
|
|
30
|
+
}
|
|
31
|
+
if (typeof console !== 'undefined' && typeof console.warn === 'function') {
|
|
32
|
+
console.warn(formatDevMessage(message));
|
|
33
|
+
}
|
|
34
|
+
};
|
|
@@ -1,3 +1,7 @@
|
|
|
1
|
+
export type EventDiagnosticsHooks = {
|
|
2
|
+
onInvalidHandler?: (propName: string, value: unknown) => void;
|
|
3
|
+
};
|
|
4
|
+
export declare const setEventDiagnosticsHooks: (hooks: EventDiagnosticsHooks | null) => void;
|
|
1
5
|
export type ParsedEventBinding = {
|
|
2
6
|
eventName: string;
|
|
3
7
|
capture: boolean;
|
|
@@ -15,4 +19,4 @@ export type ResolvedEventHandler = {
|
|
|
15
19
|
listener: EventListenerOrEventListenerObject;
|
|
16
20
|
options?: AddEventListenerOptions;
|
|
17
21
|
};
|
|
18
|
-
export declare const resolveEventHandlerValue: (value: unknown) => ResolvedEventHandler | null;
|
|
22
|
+
export declare const resolveEventHandlerValue: (propName: string, value: unknown) => ResolvedEventHandler | null;
|
|
@@ -1,3 +1,7 @@
|
|
|
1
|
+
let eventDiagnostics = null;
|
|
2
|
+
export const setEventDiagnosticsHooks = (hooks) => {
|
|
3
|
+
eventDiagnostics = hooks;
|
|
4
|
+
};
|
|
1
5
|
const captureSuffix = 'Capture';
|
|
2
6
|
const stripCaptureSuffix = (rawName) => {
|
|
3
7
|
if (rawName.endsWith(captureSuffix)) {
|
|
@@ -50,11 +54,15 @@ const isEventHandlerDescriptor = (value) => {
|
|
|
50
54
|
}
|
|
51
55
|
return isEventListenerObject(handler);
|
|
52
56
|
};
|
|
53
|
-
|
|
57
|
+
const throwInvalidHandlerError = (propName, value) => {
|
|
58
|
+
eventDiagnostics?.onInvalidHandler?.(propName, value);
|
|
59
|
+
};
|
|
60
|
+
export const resolveEventHandlerValue = (propName, value) => {
|
|
54
61
|
if (typeof value === 'function' || isEventListenerObject(value)) {
|
|
55
62
|
return { listener: value };
|
|
56
63
|
}
|
|
57
64
|
if (!isEventHandlerDescriptor(value)) {
|
|
65
|
+
throwInvalidHandlerError(propName, value);
|
|
58
66
|
return null;
|
|
59
67
|
}
|
|
60
68
|
const descriptor = value;
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import type { OxcError } from 'oxc-parser';
|
|
2
|
+
export type TemplateExpressionRange = {
|
|
3
|
+
index: number;
|
|
4
|
+
sourceStart: number;
|
|
5
|
+
sourceEnd: number;
|
|
6
|
+
};
|
|
7
|
+
export type TemplateDiagnostics = {
|
|
8
|
+
expressionRanges: TemplateExpressionRange[];
|
|
9
|
+
};
|
|
10
|
+
export type TaggedTemplateFormatOptions = {
|
|
11
|
+
label?: string;
|
|
12
|
+
};
|
|
13
|
+
export declare const formatTaggedTemplateParserError: (tagName: string, templates: TemplateStringsArray, diagnostics: TemplateDiagnostics, error: OxcError, options?: TaggedTemplateFormatOptions) => string;
|
|
@@ -0,0 +1,167 @@
|
|
|
1
|
+
const DEFAULT_LABEL = 'oxc-parser';
|
|
2
|
+
const buildTemplateDisplaySource = (templates) => {
|
|
3
|
+
const raw = templates.raw ?? templates;
|
|
4
|
+
let source = raw[0] ?? '';
|
|
5
|
+
const spans = [];
|
|
6
|
+
for (let idx = 0; idx < raw.length - 1; idx++) {
|
|
7
|
+
const label = '${expr#' + idx + '}';
|
|
8
|
+
const templateStart = source.length;
|
|
9
|
+
source += label;
|
|
10
|
+
const templateEnd = source.length;
|
|
11
|
+
spans.push({ index: idx, templateStart, templateEnd, label });
|
|
12
|
+
source += raw[idx + 1] ?? '';
|
|
13
|
+
}
|
|
14
|
+
return { source, spans };
|
|
15
|
+
};
|
|
16
|
+
const combineExpressionSpans = (diagnostics, templateSpans) => {
|
|
17
|
+
const templateSpanMap = new Map();
|
|
18
|
+
templateSpans.forEach(span => {
|
|
19
|
+
templateSpanMap.set(span.index, span);
|
|
20
|
+
});
|
|
21
|
+
return diagnostics.expressionRanges
|
|
22
|
+
.map(span => {
|
|
23
|
+
const templateSpan = templateSpanMap.get(span.index);
|
|
24
|
+
if (!templateSpan) {
|
|
25
|
+
return null;
|
|
26
|
+
}
|
|
27
|
+
const sourceLength = Math.max(0, span.sourceEnd - span.sourceStart);
|
|
28
|
+
const templateLength = Math.max(0, templateSpan.templateEnd - templateSpan.templateStart);
|
|
29
|
+
return {
|
|
30
|
+
sourceStart: span.sourceStart,
|
|
31
|
+
sourceEnd: span.sourceEnd,
|
|
32
|
+
templateStart: templateSpan.templateStart,
|
|
33
|
+
templateEnd: templateSpan.templateEnd,
|
|
34
|
+
delta: templateLength - sourceLength,
|
|
35
|
+
};
|
|
36
|
+
})
|
|
37
|
+
.filter((span) => Boolean(span))
|
|
38
|
+
.sort((a, b) => a.sourceStart - b.sourceStart);
|
|
39
|
+
};
|
|
40
|
+
const mapIndexToTemplate = (index, spans, templateLength) => {
|
|
41
|
+
if (!Number.isFinite(index) || index <= 0) {
|
|
42
|
+
return 0;
|
|
43
|
+
}
|
|
44
|
+
let delta = 0;
|
|
45
|
+
for (const span of spans) {
|
|
46
|
+
if (index < span.sourceStart) {
|
|
47
|
+
break;
|
|
48
|
+
}
|
|
49
|
+
if (index < span.sourceEnd) {
|
|
50
|
+
const relative = Math.max(0, index - span.sourceStart);
|
|
51
|
+
const templateSpanLength = Math.max(0, span.templateEnd - span.templateStart);
|
|
52
|
+
if (templateSpanLength === 0) {
|
|
53
|
+
return span.templateStart;
|
|
54
|
+
}
|
|
55
|
+
const clamped = Math.min(relative, Math.max(0, templateSpanLength - 1));
|
|
56
|
+
return span.templateStart + clamped;
|
|
57
|
+
}
|
|
58
|
+
delta += span.delta;
|
|
59
|
+
}
|
|
60
|
+
const mapped = index + delta;
|
|
61
|
+
if (mapped <= 0) {
|
|
62
|
+
return 0;
|
|
63
|
+
}
|
|
64
|
+
if (mapped >= templateLength) {
|
|
65
|
+
return templateLength;
|
|
66
|
+
}
|
|
67
|
+
return mapped;
|
|
68
|
+
};
|
|
69
|
+
const getLineAndColumnFromIndex = (source, index) => {
|
|
70
|
+
const limit = Math.max(0, Math.min(index, source.length));
|
|
71
|
+
let line = 1;
|
|
72
|
+
let column = 1;
|
|
73
|
+
for (let idx = 0; idx < limit; idx++) {
|
|
74
|
+
if (source.charCodeAt(idx) === 10) {
|
|
75
|
+
line++;
|
|
76
|
+
column = 1;
|
|
77
|
+
continue;
|
|
78
|
+
}
|
|
79
|
+
column++;
|
|
80
|
+
}
|
|
81
|
+
return { line, column };
|
|
82
|
+
};
|
|
83
|
+
const computeLineOffsets = (lines) => {
|
|
84
|
+
const offsets = [];
|
|
85
|
+
let cursor = 0;
|
|
86
|
+
lines.forEach((line, index) => {
|
|
87
|
+
offsets.push(cursor);
|
|
88
|
+
cursor += line.length;
|
|
89
|
+
if (index < lines.length - 1) {
|
|
90
|
+
cursor += 1;
|
|
91
|
+
}
|
|
92
|
+
});
|
|
93
|
+
return offsets;
|
|
94
|
+
};
|
|
95
|
+
const createPointerLine = (lineNumber, lineText, lineStartOffset, rangeStart, rangeEnd, startLine, endLine) => {
|
|
96
|
+
const lineEndOffset = lineStartOffset + lineText.length;
|
|
97
|
+
const overlapStart = Math.max(rangeStart, lineStartOffset);
|
|
98
|
+
const overlapEnd = Math.min(rangeEnd, lineEndOffset);
|
|
99
|
+
if (overlapEnd > overlapStart) {
|
|
100
|
+
const pointerStart = Math.max(0, overlapStart - lineStartOffset);
|
|
101
|
+
const pointerWidth = Math.max(1, overlapEnd - overlapStart);
|
|
102
|
+
return ' '.repeat(pointerStart) + '^'.repeat(pointerWidth);
|
|
103
|
+
}
|
|
104
|
+
if (lineText.length === 0 && lineNumber >= startLine && lineNumber <= endLine) {
|
|
105
|
+
return '^';
|
|
106
|
+
}
|
|
107
|
+
if (lineNumber === startLine) {
|
|
108
|
+
const caretPos = Math.max(0, rangeStart - lineStartOffset);
|
|
109
|
+
return ' '.repeat(Math.min(caretPos, lineText.length)) + '^';
|
|
110
|
+
}
|
|
111
|
+
return '';
|
|
112
|
+
};
|
|
113
|
+
const buildCodeFrame = (source, start, end, startLine, endLine) => {
|
|
114
|
+
if (!source.length) {
|
|
115
|
+
return '';
|
|
116
|
+
}
|
|
117
|
+
const lines = source.split('\n');
|
|
118
|
+
const offsets = computeLineOffsets(lines);
|
|
119
|
+
const frameStart = Math.max(1, startLine - 1);
|
|
120
|
+
const frameEnd = Math.min(lines.length, endLine + 1);
|
|
121
|
+
const gutterWidth = String(frameEnd).length;
|
|
122
|
+
const frame = [];
|
|
123
|
+
for (let lineNumber = frameStart; lineNumber <= frameEnd; lineNumber++) {
|
|
124
|
+
const lineText = lines[lineNumber - 1] ?? '';
|
|
125
|
+
const gutter = String(lineNumber).padStart(gutterWidth, ' ');
|
|
126
|
+
frame.push(`${gutter} | ${lineText}`);
|
|
127
|
+
const pointer = createPointerLine(lineNumber, lineText, offsets[lineNumber - 1] ?? 0, start, end, startLine, endLine);
|
|
128
|
+
if (pointer) {
|
|
129
|
+
frame.push(`${' '.repeat(gutterWidth)} | ${pointer}`);
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
return frame.join('\n');
|
|
133
|
+
};
|
|
134
|
+
export const formatTaggedTemplateParserError = (tagName, templates, diagnostics, error, options) => {
|
|
135
|
+
const label = options?.label ?? DEFAULT_LABEL;
|
|
136
|
+
const fallback = `[${label}] ${error.message}`;
|
|
137
|
+
const primaryLabel = error.labels?.[0];
|
|
138
|
+
if (!primaryLabel) {
|
|
139
|
+
return fallback;
|
|
140
|
+
}
|
|
141
|
+
const { source: templateSource, spans } = buildTemplateDisplaySource(templates);
|
|
142
|
+
const combinedSpans = combineExpressionSpans(diagnostics, spans);
|
|
143
|
+
const mapIndex = (value) => {
|
|
144
|
+
const numeric = typeof value === 'number' ? value : 0;
|
|
145
|
+
return mapIndexToTemplate(numeric, combinedSpans, templateSource.length);
|
|
146
|
+
};
|
|
147
|
+
const startIndex = mapIndex(primaryLabel.start);
|
|
148
|
+
let endIndex = mapIndex(primaryLabel.end);
|
|
149
|
+
if (endIndex <= startIndex) {
|
|
150
|
+
endIndex = Math.min(templateSource.length, startIndex + 1);
|
|
151
|
+
}
|
|
152
|
+
const startLocation = getLineAndColumnFromIndex(templateSource, startIndex);
|
|
153
|
+
const endLocation = getLineAndColumnFromIndex(templateSource, Math.max(startIndex, endIndex - 1));
|
|
154
|
+
const codeframe = buildCodeFrame(templateSource, startIndex, endIndex, startLocation.line, endLocation.line);
|
|
155
|
+
let message = `[${label}] ${error.message}`;
|
|
156
|
+
message += `\n--> ${tagName} template:${startLocation.line}:${startLocation.column}`;
|
|
157
|
+
if (primaryLabel.message) {
|
|
158
|
+
message += `\n${primaryLabel.message}`;
|
|
159
|
+
}
|
|
160
|
+
if (codeframe) {
|
|
161
|
+
message += `\n${codeframe}`;
|
|
162
|
+
}
|
|
163
|
+
if (error.helpMessage) {
|
|
164
|
+
message += `\n${error.helpMessage}`;
|
|
165
|
+
}
|
|
166
|
+
return message;
|
|
167
|
+
};
|
package/dist/jsx.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { parseSync } from 'oxc-parser';
|
|
2
|
-
import { buildTemplate, evaluateExpression, extractRootNode,
|
|
2
|
+
import { buildTemplate, evaluateExpression, extractRootNode, formatTaggedTemplateParserError, getIdentifierName, normalizeJsxTextSegments, parserOptions, } from './runtime/shared.js';
|
|
3
3
|
import { find as findPropertyInfo, html as htmlProperties, svg as svgProperties, } from 'property-information';
|
|
4
4
|
import { createResolveAttributes, } from './internal/attribute-resolution.js';
|
|
5
5
|
import { parseEventPropName, resolveEventHandlerValue, } from './internal/event-bindings.js';
|
|
@@ -113,7 +113,7 @@ const setDomProp = (element, name, value, namespace) => {
|
|
|
113
113
|
}
|
|
114
114
|
const eventBinding = parseEventPropName(name);
|
|
115
115
|
if (eventBinding) {
|
|
116
|
-
const handlerValue = resolveEventHandlerValue(value);
|
|
116
|
+
const handlerValue = resolveEventHandlerValue(name, value);
|
|
117
117
|
if (handlerValue) {
|
|
118
118
|
let options = handlerValue.options ? { ...handlerValue.options } : undefined;
|
|
119
119
|
if (eventBinding.capture) {
|
|
@@ -308,7 +308,7 @@ export const jsx = (templates, ...values) => {
|
|
|
308
308
|
const build = buildTemplate(templates, values);
|
|
309
309
|
const result = parseSync('inline.jsx', build.source, parserOptions);
|
|
310
310
|
if (result.errors.length > 0) {
|
|
311
|
-
throw new Error(
|
|
311
|
+
throw new Error(formatTaggedTemplateParserError('jsx', templates, build.diagnostics, result.errors[0]));
|
|
312
312
|
}
|
|
313
313
|
const root = extractRootNode(result.program);
|
|
314
314
|
const ctx = {
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
var k=e=>{e?.mode??"env";},A=()=>{};export{A as disableJsxDebugDiagnostics,k as enableJsxDebugDiagnostics};
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import {parseSync}from'oxc-parser';import {find,svg,html}from'property-information';var T=null,$=e=>{T=e;},oe=e=>{T?.warnLowercaseEventProp?.(e);},se=e=>{T?.ensureValidDangerouslySetInnerHTML?.(e);},P=e=>{let{getIdentifierName:t,evaluateExpressionWithNamespace:n}=e;return (r,o,s)=>{let i={},p=(a,c)=>{a==="dangerouslySetInnerHTML"&&se(c),i[a]=c;};return r.forEach(a=>{if(a.type==="JSXSpreadAttribute"){let l=n(a.argument,o,s);l&&typeof l=="object"&&!Array.isArray(l)&&Object.assign(i,l);return}let c=t(a.name);if(oe(c),!a.value){p(c,true);return}if(a.value.type==="Literal"){p(c,a.value.value);return}if(a.value.type==="JSXExpressionContainer"){if(a.value.expression.type==="JSXEmptyExpression")return;p(c,n(a.value.expression,o,s));}}),i}};var L=null,O=e=>{L=e;},j="Capture",I=e=>e.endsWith(j)?{eventName:e.slice(0,-j.length),capture:true}:{eventName:e,capture:false},_=e=>{if(!e.startsWith("on"))return null;if(e.startsWith("on:")){let r=e.slice(3);if(!r)return null;let o=I(r);return o.eventName?o:null}let t=e.slice(2);if(!t)return null;let n=I(t);return n.eventName?{eventName:n.eventName.toLowerCase(),capture:n.capture}:null},H=e=>!e||typeof e!="object"?false:"handleEvent"in e&&typeof e.handleEvent=="function",ae=e=>{if(!e||typeof e!="object"||!("handler"in e))return false;let t=e.handler;return typeof t=="function"?true:H(t)},ie=(e,t)=>{L?.onInvalidHandler?.(e,t);},F=(e,t)=>{if(typeof t=="function"||H(t))return {listener:t};if(!ae(t))return ie(e,t),null;let n=t,r=n.options?{...n.options}:void 0,o=(s,i)=>{i!=null&&(r||(r={}),r[s]=i);};return o("capture",n.capture),o("once",n.once),o("passive",n.passive),o("signal",n.signal??void 0),{listener:n.handler,options:r}};var pe="@knighted/jsx",B=e=>`${pe}: ${e}`,J=()=>typeof process<"u"&&process.env?.KNIGHTED_JSX_DEBUG==="1",C=e=>{if(e===null)return "null";if(e===void 0)return "undefined";if(typeof e=="function")return e.name?`function ${e.name}`:"function";if(Array.isArray(e))return "array";if(typeof e=="object"){let t=e.constructor;return t&&typeof t.name=="string"&&t.name&&t.name!=="Object"?`${t.name} instance`:"object"}return typeof e},b=e=>new Error(B(e)),W=(e,t=false)=>{!t&&!J()||typeof console<"u"&&typeof console.warn=="function"&&console.warn(B(e));};var ce=e=>e>="a"&&e<="z",S="env",A=()=>S==="always"||S==="env"&&J(),le=()=>S==="always",me={warnLowercaseEventProp(e){if(!A()||!e.startsWith("on")||e.startsWith("on:")||e.length<3)return;let t=e[2]??"";if(!ce(t))return;let n=`${e.slice(0,2)}${t.toUpperCase()}${e.slice(3)}`;W(`Use camelCase DOM event props when targeting runtime jsx templates. Received "${e}"; did you mean "${n}"?`,le());},ensureValidDangerouslySetInnerHTML(e){if(!A())return;if(!e||typeof e!="object"||Array.isArray(e))throw b("dangerouslySetInnerHTML expects an object with a string __html field.");let t=e.__html;if(typeof t!="string")throw b(`dangerouslySetInnerHTML.__html must be a string but received ${C(t)}.`)}},ue={onInvalidHandler(e,t){if(A())throw b(`The "${e}" prop expects a function, EventListenerObject, or descriptor ({ handler }) but received ${C(t)}.`)}},V=e=>{S=e?.mode,$(me),O(ue);};var de="oxc-parser",ge=e=>{let t=e.raw??e,n=t[0]??"",r=[];for(let o=0;o<t.length-1;o++){let s="${expr#"+o+"}",i=n.length;n+=s;let p=n.length;r.push({index:o,templateStart:i,templateEnd:p,label:s}),n+=t[o+1]??"";}return {source:n,spans:r}},fe=(e,t)=>{let n=new Map;return t.forEach(r=>{n.set(r.index,r);}),e.expressionRanges.map(r=>{let o=n.get(r.index);if(!o)return null;let s=Math.max(0,r.sourceEnd-r.sourceStart),i=Math.max(0,o.templateEnd-o.templateStart);return {sourceStart:r.sourceStart,sourceEnd:r.sourceEnd,templateStart:o.templateStart,templateEnd:o.templateEnd,delta:i-s}}).filter(r=>!!r).sort((r,o)=>r.sourceStart-o.sourceStart)},xe=(e,t,n)=>{if(!Number.isFinite(e)||e<=0)return 0;let r=0;for(let s of t){if(e<s.sourceStart)break;if(e<s.sourceEnd){let i=Math.max(0,e-s.sourceStart),p=Math.max(0,s.templateEnd-s.templateStart);if(p===0)return s.templateStart;let a=Math.min(i,Math.max(0,p-1));return s.templateStart+a}r+=s.delta;}let o=e+r;return o<=0?0:o>=n?n:o},U=(e,t)=>{let n=Math.max(0,Math.min(t,e.length)),r=1,o=1;for(let s=0;s<n;s++){if(e.charCodeAt(s)===10){r++,o=1;continue}o++;}return {line:r,column:o}},ye=e=>{let t=[],n=0;return e.forEach((r,o)=>{t.push(n),n+=r.length,o<e.length-1&&(n+=1);}),t},Ee=(e,t,n,r,o,s,i)=>{let p=n+t.length,a=Math.max(r,n),c=Math.min(o,p);if(c>a){let l=Math.max(0,a-n),u=Math.max(1,c-a);return " ".repeat(l)+"^".repeat(u)}if(t.length===0&&e>=s&&e<=i)return "^";if(e===s){let l=Math.max(0,r-n);return " ".repeat(Math.min(l,t.length))+"^"}return ""},he=(e,t,n,r,o)=>{if(!e.length)return "";let s=e.split(`
|
|
2
|
+
`),i=ye(s),p=Math.max(1,r-1),a=Math.min(s.length,o+1),c=String(a).length,l=[];for(let u=p;u<=a;u++){let d=s[u-1]??"",m=String(u).padStart(c," ");l.push(`${m} | ${d}`);let g=Ee(u,d,i[u-1]??0,t,n,r,o);g&&l.push(`${" ".repeat(c)} | ${g}`);}return l.join(`
|
|
3
|
+
`)},k=(e,t,n,r,o)=>{let s=de,i=`[${s}] ${r.message}`,p=r.labels?.[0];if(!p)return i;let{source:a,spans:c}=ge(t),l=fe(n,c),u=y=>xe(typeof y=="number"?y:0,l,a.length),d=u(p.start),m=u(p.end);m<=d&&(m=Math.min(a.length,d+1));let g=U(a,d),x=U(a,Math.max(d,m-1)),h=he(a,d,m,g.line,x.line),f=`[${s}] ${r.message}`;return f+=`
|
|
4
|
+
--> ${e} template:${g.line}:${g.column}`,p.message&&(f+=`
|
|
5
|
+
${p.message}`),h&&(f+=`
|
|
6
|
+
${h}`),r.helpMessage&&(f+=`
|
|
7
|
+
${r.helpMessage}`),f};var be=/<\s*$/,Se=/<\/\s*$/,K="__KX_EXPR__",z=new RegExp(`${K}\\d+_\\d+__`,"g"),we=0;var G={lang:"jsx",sourceType:"module",range:true,preserveParens:true},Z=e=>{for(let t of e.body)if(t.type==="ExpressionStatement"){let n=t.expression;if(n.type==="JSXElement"||n.type==="JSXFragment")return n}throw new Error("The jsx template must contain a single JSX element or fragment.")},w=e=>{switch(e.type){case "JSXIdentifier":return e.name;case "JSXNamespacedName":return `${e.namespace.name}:${e.name.name}`;case "JSXMemberExpression":return `${w(e.object)}.${e.property.name}`;default:return ""}},v=(e,t)=>{if(!e||typeof e!="object")return;let n=e;typeof n.type=="string"&&(t(n),Object.values(n).forEach(r=>{if(r){if(Array.isArray(r)){r.forEach(o=>v(o,t));return}typeof r=="object"&&v(r,t);}}));},q=(e,t)=>{let n=e.replace(/\r/g,"").replace(/\n\s+/g," "),r=e.match(/^\s*/)?.[0]??"",o=e.match(/\s*$/)?.[0]??"",s=/\n/.test(r),i=/\n/.test(o),p=n;if(s&&(p=p.replace(/^\s+/,"")),i&&(p=p.replace(/\s+$/,"")),p.length===0||p.trim().length===0)return [];let a=[];z.lastIndex=0;let c=0,l;for(;l=z.exec(p);){let d=l.index,m=p.slice(c,d);m&&a.push(m);let g=l[0];t.has(g)?a.push(t.get(g)):a.push(g),c=d+g.length;}let u=p.slice(c);return u&&a.push(u),a},Te=(e,t)=>{let n=new Set;return v(e,r=>{r.type==="Identifier"&&t.placeholders.has(r.name)&&n.add(r.name);}),Array.from(n)},Q=(e,t,n)=>{if(e.type==="JSXElement"||e.type==="JSXFragment")return n(e);if(!("range"in e)||!e.range)throw new Error("Unable to evaluate expression: missing source range information.");let[r,o]=e.range,s=t.source.slice(r,o),i=Te(e,t);try{let p=new Function(...i,`"use strict"; return (${s});`),a=i.map(c=>t.placeholders.get(c));return p(...a)}catch(p){throw new Error(`Failed to evaluate expression ${s}: ${p.message}`)}},Je=e=>{let t=e.replace(/[^a-zA-Z0-9_$]/g,"");return t?/[A-Za-z_$]/.test(t[0])?t:`Component${t}`:"Component"},Ce=(e,t,n)=>{let r=n.get(e);if(r)return r;let o=e.displayName||e.name||`Component${t.length}`,s=Je(o??""),i=s,p=1;for(;t.some(c=>c.name===i);)i=`${s}${p++}`;let a={name:i,value:e};return t.push(a),n.set(e,a),a},Y=(e,t)=>{let n=e.raw??e,r=new Map,o=[],s=new Map,i=n[0]??"",p=we++,a=0,c=[];for(let l=0;l<t.length;l++){let u=n[l]??"",d=n[l+1]??"",m=t[l],g=be.test(u)||Se.test(u),x;if(g&&typeof m=="function")x=Ce(m,o,s).name;else if(g&&typeof m=="string")x=m;else {let y=`${K}${p}_${a++}__`;r.set(y,m),x=y;}let h=i.length;i+=x;let f=i.length;c.push({index:l,sourceStart:h,sourceEnd:f}),i+=d;}return {source:i,placeholders:r,bindings:o,diagnostics:{expressionRanges:c}}};var Ne=()=>{if(typeof document>"u"||typeof document.createElement!="function")throw new Error("The jsx template tag requires a DOM-like environment (document missing).")},Xe=e=>typeof Node>"u"?false:e instanceof Node||e instanceof DocumentFragment,Re=e=>!e||typeof e=="string"?false:typeof e[Symbol.iterator]=="function",te=e=>!e||typeof e!="object"&&typeof e!="function"?false:typeof e.then=="function",Me={xlink:"http://www.w3.org/1999/xlink",xml:"http://www.w3.org/XML/1998/namespace",xmlns:"http://www.w3.org/2000/xmlns/"},ne=e=>{if(!(!e||e==="html"||e==="svg"))return Me[e]},$e=e=>e==="svg"?svg:html,D=(e,t,n)=>{let r=ne(t.space),o=String(n);if(r){e.setAttributeNS(r,t.attribute,o);return}e.setAttribute(t.attribute,o);},ee=(e,t)=>{let n=ne(t.space);if(n){e.removeAttributeNS(n,t.attribute);return}e.removeAttribute(t.attribute);},N=(e,t)=>Array.isArray(e)?e.filter(Boolean).join(t):e,Pe=(e,t,n)=>t==="svg"||!n.property||n.property.includes(":")?false:n.property in e,je=(e,t,n,r)=>{if(n==null)return;if(t==="dangerouslySetInnerHTML"&&typeof n=="object"&&n&&"__html"in n){e.innerHTML=String(n.__html??"");return}if(t==="ref"){if(typeof n=="function"){n(e);return}if(n&&typeof n=="object"){n.current=e;return}}if(t==="style"&&typeof n=="object"&&n!==null){let c=n,l=e.style;if(!l)return;let u=l;Object.entries(c).forEach(([d,m])=>{if(m!=null){if(d.startsWith("--")){l.setProperty(d,String(m));return}u[d]=m;}});return}let o=_(t);if(o){let c=F(t,n);if(c){let l=c.options?{...c.options}:void 0;o.capture&&(l?l.capture=true:l={capture:true}),e.addEventListener(o.eventName,c.listener,l);return}}let s=find($e(r),t),i=e,p=Pe(e,r,s);if(s.mustUseProperty){let c=s.boolean?!!n:n;i[s.property]=c;return}if(s.boolean){let c=!!n;p&&(i[s.property]=c),c?D(e,s,""):ee(e,s);return}let a=n;if(s.spaceSeparated?a=N(n," "):s.commaSeparated?a=N(n,","):s.commaOrSpaceSeparated&&(a=N(n," ")),s.booleanish&&typeof a=="boolean"&&(a=a?"true":"false"),s.overloadedBoolean){if(a===false){ee(e,s);return}if(a===true){D(e,s,"");return}}if(p){i[s.property]=a;return}a!==false&&D(e,s,a);},E=(e,t)=>{if(t!=null&&typeof t!="boolean"){if(te(t))throw new Error("Async values are not supported inside jsx template results.");if(Array.isArray(t)){t.forEach(n=>E(e,n));return}if(Re(t)){for(let n of t)E(e,n);return}if(Xe(t)){e.appendChild(t);return}e.appendChild(document.createTextNode(String(t)));}},X=(e,t,n)=>Q(e,t,r=>M(r,t,n)),re=P({getIdentifierName:w,evaluateExpressionWithNamespace:X}),Ie=(e,t,n,r)=>{let o=re(t,n,r);Object.entries(o).forEach(([s,i])=>{if(s!=="key"){if(s==="children"){E(e,i);return}je(e,s,i,r);}});},R=(e,t,n)=>{let r=[];return e.forEach(o=>{switch(o.type){case "JSXText":{q(o.value,t.placeholders).forEach(i=>{r.push(i);});break}case "JSXExpressionContainer":{if(o.expression.type==="JSXEmptyExpression")break;r.push(X(o.expression,t,n));break}case "JSXSpreadChild":{let s=X(o.expression,t,n);s!=null&&r.push(s);break}case "JSXElement":case "JSXFragment":{r.push(M(o,t,n));break}}}),r},Le=(e,t,n,r)=>{let o=re(e.openingElement.attributes,t,r),s=R(e.children,t,r);s.length===1?o.children=s[0]:s.length>1&&(o.children=s);let i=n(o);if(te(i))throw new Error("Async jsx components are not supported.");return i},Oe=(e,t,n)=>{let r=e.openingElement,o=w(r.name),s=t.components.get(o);if(s)return Le(e,t,s,n);if(/[A-Z]/.test(o[0]??""))throw new Error(`Unknown component "${o}". Did you interpolate it with the template literal?`);let i=o==="svg"?"svg":n,p=o==="foreignObject"?null:i,a=i==="svg"?document.createElementNS("http://www.w3.org/2000/svg",o):document.createElement(o);return Ie(a,r.attributes,t,i),R(e.children,t,p).forEach(l=>E(a,l)),a},M=(e,t,n)=>{if(e.type==="JSXFragment"){let r=document.createDocumentFragment();return R(e.children,t,n).forEach(s=>E(r,s)),r}return Oe(e,t,n)},_e=(e,...t)=>{Ne();let n=Y(e,t),r=parseSync("inline.jsx",n.source,G);if(r.errors.length>0)throw new Error(k("jsx",e,n.diagnostics,r.errors[0]));let o=Z(r.program),s={source:n.source,placeholders:n.placeholders,components:new Map(n.bindings.map(i=>[i.name,i.value]))};return M(o,s,null)};V({mode:"always"});
|
|
8
|
+
export{_e as jsx};
|