@litsx/babel-plugin-transform-litsx-scoped-elements
Source: test/babel-plugin-transform-litsx-scoped-elements.test.js
Generated from transform tests.
Pipeline
@litsx/babel-plugin-transform-litsx-scoped-elements
Covered Cases
Wraps LitElement with ShadowDomElementsMixin and registers tags
Interpretation
This case records the authored input and the generated output as a living transform contract.
Authored Input
import { LitElement, html } from 'lit';
import FancyButton from './FancyButton.js';
class MyElement extends LitElement {
render() {
return <FancyButton>Click me</FancyButton>;
}
}Generated Output
import { ShadowDomElementsMixin } from "litsx/runtime-infrastructure";
import { LitElement, html } from 'lit';
import FancyButton from './FancyButton.js';
class MyElement extends ShadowDomElementsMixin(LitElement) {
render() {
return <fancy-button>Click me</fancy-button>;
}
static elements = {
"fancy-button": FancyButton
};
}Handles React-style function components with useRef
Interpretation
This case captures supported authored syntax and the emitted code path used to preserve that behavior.
Authored Input
import { useRef, useEffect } from 'react';
import PropTypes from 'prop-types';
import FancyButton from './FancyButton.js';
const FancyForm = (props) => {
const buttonRef = useRef(null);
useEffect(() => {
buttonRef.current.focus();
}, []);
return (
<div>
<FancyButton ref={buttonRef} .label={props.label} />
</div>
);
};
FancyForm.propTypes = {
label: PropTypes.string,
};
export const Alert = (message) => {
const lower = message.toLowerCase();
return <p>{lower}</p>;
};Generated Output
import { useRef, useEffect } from 'react';
import PropTypes from 'prop-types';
import FancyButton from './FancyButton.js';
const FancyForm = props => {
const buttonRef = useRef(null);
useEffect(() => {
buttonRef.current.focus();
}, []);
return <div>
<FancyButton ref={buttonRef} .label={props.label} />
</div>;
};
FancyForm.propTypes = {
label: PropTypes.string
};
export const Alert = message => {
const lower = message.toLowerCase();
return <p>{lower}</p>;
};Detects scoped usage inside html tagged templates
Interpretation
This case records the authored input and the generated output as a living transform contract.
Authored Input
import { LitElement, html } from 'lit';
import FancyButton from './FancyButton.js';
class TemplateElement extends LitElement {
render() {
return html\`<section><FancyButton></FancyButton></section>\Generated Error
Expecting Unicode escape sequence \uXXXX. (6:22)Inserts elements after existing properties
Interpretation
This case records the authored input and the generated output as a living transform contract.
Authored Input
import { LitElement, html } from 'lit';
import FancyButton from './FancyButton.js';
class WithProperties extends LitElement {
static properties = {
label: { type: String }
};
render() {
return <FancyButton label={this.label} />;
}
}Generated Output
import { ShadowDomElementsMixin } from "litsx/runtime-infrastructure";
import { LitElement, html } from 'lit';
import FancyButton from './FancyButton.js';
class WithProperties extends ShadowDomElementsMixin(LitElement) {
static properties = {
label: {
type: String
}
};
static elements = {
"fancy-button": FancyButton
};
render() {
return <fancy-button label={this.label} />;
}
}Leaves classes without scoped usage untouched
Interpretation
This case highlights syntax that should survive the transform unchanged or be preserved semantically.
Authored Input
import { LitElement, html } from 'lit';
class PlainElement extends LitElement {
render() {
return html\`<div>No scoped elements here</div>\Generated Error
Expecting Unicode escape sequence \uXXXX. (5:22)Uses LightDomElementsMixin for light DOM dependencies
Interpretation
This case records the authored input and the generated output as a living transform contract.
Authored Input
import FancyButton from './FancyButton.js';
function LightScreen() {
^lightDom();
return <FancyButton />;
}Generated Output
import FancyButton from './FancyButton.js';
function LightScreen() {
__litsx_static_lightDom();
return <FancyButton />;
}Uses LightDomMixin for light DOM components without element dependencies
Interpretation
This case records the authored input and the generated output as a living transform contract.
Authored Input
function LightCard() {
^lightDom();
return <div>ready</div>;
}Generated Output
function LightCard() {
__litsx_static_lightDom();
return <div>ready</div>;
}Reuses an existing ShadowDomElementsMixin import
Interpretation
This case records the authored input and the generated output as a living transform contract.
Authored Input
import { LitElement } from 'lit';
import { ShadowDomElementsMixin } from 'litsx/runtime-infrastructure';
import FancyButton from './FancyButton.js';
class ReadyElement extends LitElement {
render() {
return <FancyButton />;
}
}Generated Output
import { LitElement } from 'lit';
import { ShadowDomElementsMixin } from 'litsx/runtime-infrastructure';
import FancyButton from './FancyButton.js';
class ReadyElement extends ShadowDomElementsMixin(LitElement) {
render() {
return <fancy-button />;
}
static elements = {
"fancy-button": FancyButton
};
}Supports classes extending mixins around LitElement
Interpretation
This case captures supported authored syntax and the emitted code path used to preserve that behavior.
Authored Input
import FancyButton from './FancyButton.js';
class MixedElement extends withTheme(LitElement) {
render() {
return <FancyButton></FancyButton>;
}
}Generated Output
import { ShadowDomElementsMixin } from "litsx/runtime-infrastructure";
import FancyButton from './FancyButton.js';
class MixedElement extends ShadowDomElementsMixin(withTheme(LitElement)) {
render() {
return <fancy-button></fancy-button>;
}
static elements = {
"fancy-button": FancyButton
};
}Does not duplicate ShadowDomElementsMixin when it is nested inside another mixin
Interpretation
This case records the authored input and the generated output as a living transform contract.
Authored Input
import { ShadowDomElementsMixin } from 'litsx/runtime-infrastructure';
import FancyButton from './FancyButton.js';
class MixedElement extends withTheme(ShadowDomElementsMixin(LitElement)) {
render() {
return <FancyButton />;
}
}Generated Output
import { ShadowDomElementsMixin } from 'litsx/runtime-infrastructure';
import FancyButton from './FancyButton.js';
class MixedElement extends withTheme(ShadowDomElementsMixin(LitElement)) {
render() {
return <fancy-button />;
}
static elements = {
"fancy-button": FancyButton
};
}Does not duplicate LightDomMixin when it is nested inside another mixin
Interpretation
This case records the authored input and the generated output as a living transform contract.
Authored Input
import { LightDomMixin } from 'litsx/runtime-infrastructure';
class MixedLightCard extends withTheme(LightDomMixin(LitElement)) {
render() {
return <div>ready</div>;
}
}
MixedLightCard._litsxLightDom = true;Generated Output
import { LightDomMixin } from 'litsx/runtime-infrastructure';
class MixedLightCard extends withTheme(LightDomMixin(LitElement)) {
render() {
return <div>ready</div>;
}
}
MixedLightCard._litsxLightDom = true;Rewrites JSX opening tags with attributes to kebab-case consistently
Interpretation
This case shows the authored JSX/API surface and the normalized output produced by the compatibility transform.
Authored Input
import { LitElement } from 'lit';
import FancyButton from './FancyButton.js';
class AttributedElement extends LitElement {
render() {
return <FancyButton label={this.label}>Click</FancyButton>;
}
}Generated Output
import { ShadowDomElementsMixin } from "litsx/runtime-infrastructure";
import { LitElement } from 'lit';
import FancyButton from './FancyButton.js';
class AttributedElement extends ShadowDomElementsMixin(LitElement) {
render() {
return <fancy-button label={this.label}>Click</fancy-button>;
}
static elements = {
"fancy-button": FancyButton
};
}Registers locally defined sibling components used in JSX
Interpretation
This case records the authored input and the generated output as a living transform contract.
Authored Input
import { LitElement } from 'lit';
export class ProfileChip extends LitElement {
render() {
return <article>chip</article>;
}
}
export class ProfileScreen extends LitElement {
render() {
return <ProfileChip />;
}
}Generated Output
import { ShadowDomElementsMixin } from "litsx/runtime-infrastructure";
import { LitElement } from 'lit';
export class ProfileChip extends LitElement {
render() {
return <article>chip</article>;
}
}
export class ProfileScreen extends ShadowDomElementsMixin(LitElement) {
render() {
return <profile-chip />;
}
static elements = {
"profile-chip": ProfileChip
};
}Registers the current class when it is used recursively as a JSX tag
Interpretation
This case records the authored input and the generated output as a living transform contract.
Authored Input
import { LitElement } from 'lit';
export class TreeNode extends LitElement {
render() {
return (
<section>
<TreeNode />
</section>
);
}
}Generated Output
import { ShadowDomElementsMixin } from "litsx/runtime-infrastructure";
import { LitElement } from 'lit';
export class TreeNode extends ShadowDomElementsMixin(LitElement) {
render() {
return <section>
<tree-node />
</section>;
}
static elements = {
"tree-node": TreeNode
};
}Emits the same base tag for light DOM components from different sources
Interpretation
This case records the authored input and the generated output as a living transform contract.
- No inline source fixture extracted for this case.
Keeps the same light DOM tag for the same imported constructor source
Interpretation
This case highlights syntax that should survive the transform unchanged or be preserved semantically.
Authored Input
import ProfileChip from './profile/ProfileChip.js';
export function FirstScreen() {
^lightDom();
return <ProfileChip />;
}
export function SecondScreen() {
^lightDom();
return <ProfileChip />;
}Generated Output
import ProfileChip from './profile/ProfileChip.js';
export function FirstScreen() {
__litsx_static_lightDom();
return <ProfileChip />;
}
export function SecondScreen() {
__litsx_static_lightDom();
return <ProfileChip />;
}Still rewrites scoped tags when candidates were precomputed by transform-litsx
Interpretation
This case shows the authored JSX/API surface and the normalized output produced by the compatibility transform.
Authored Input
import { SuspenseBoundary } from 'litsx';
export function Screen() {
return (
<section>
<SuspenseBoundary fallback={<span>loading</span>}>
<span>ready</span>
</SuspenseBoundary>
</section>
);
}Generated Output
import { SuspenseBoundary } from 'litsx';
export function Screen() {
return <section>
<SuspenseBoundary fallback={<span>loading</span>}>
<span>ready</span>
</SuspenseBoundary>
</section>;
}Rewrites scoped tags nested inside keyed(...) expressions
Interpretation
This case shows the authored JSX/API surface and the normalized output produced by the compatibility transform.
Authored Input
import { keyed } from 'lit/directives/keyed.js';
import { SuspenseBoundary } from 'litsx';
export function Screen({ cycle }) {
return (
<section>
{keyed(cycle, (
<SuspenseBoundary fallback={<span>loading</span>}>
<span>ready</span>
</SuspenseBoundary>
))}
</section>
);
}Generated Output
import { keyed } from 'lit/directives/keyed.js';
import { SuspenseBoundary } from 'litsx';
export function Screen({
cycle
}) {
return <section>
{keyed(cycle, <SuspenseBoundary fallback={<span>loading</span>}>
<span>ready</span>
</SuspenseBoundary>)}
</section>;
}Rewrites scoped tags inside nested html templates under keyed(...) expressions
Interpretation
This case shows the authored JSX/API surface and the normalized output produced by the compatibility transform.
Authored Input
import { LitElement, html } from 'lit';
import { keyed } from 'lit/directives/keyed.js';
import { SuspenseBoundary, SuspenseList } from 'litsx';
class Screen extends LitElement {
render() {
return html\`
<SuspenseList reveal-order="forwards">
\${keyed(this.cycle, html\`
<SuspenseBoundary fallback=\${html\`<span>loading</span>\`}>
<span>ready</span>
</SuspenseBoundary>
\`)}
</SuspenseList>
\Generated Error
Expecting Unicode escape sequence \uXXXX. (7:22)