Skip to content

Commit 683fb92

Browse files
author
Bob Fanger
committed
feat: Add support for dot notation
Fixed #12
1 parent 05d4050 commit 683fb92

File tree

4 files changed

+58
-11
lines changed

4 files changed

+58
-11
lines changed

src/lib/preprocessReact.ts

Lines changed: 19 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -112,14 +112,15 @@ function transform(content: string, options: TransformOptions) {
112112
});
113113
const s = new MagicString(content, { filename: options.filename });
114114
const components = replaceReactTags(compiled.ast.html, s);
115+
const aliases = Object.entries(components);
115116

116-
if (components.length === 0) {
117+
if (aliases.length === 0) {
117118
return { code: content };
118119
}
119120
const script = compiled.ast.instance || (compiled.ast.module as Script);
120-
const wrappers = components
121-
.map((component) => {
122-
return `const React$${component} = ${prefix}sveltify(${component}, ${portal}, ${prefix}ReactDOM${renderToString});`;
121+
const wrappers = aliases
122+
.map(([alias, expression]) => {
123+
return `const ${alias} = ${prefix}sveltify(${expression}, ${portal}, ${prefix}ReactDOM${renderToString});`;
123124
})
124125
.join(";");
125126

@@ -138,21 +139,28 @@ function transform(content: string, options: TransformOptions) {
138139
function replaceReactTags(
139140
node: TemplateNode,
140141
content: MagicString,
141-
components: string[] = []
142+
components: Record<string, string> = {}
142143
) {
143144
/* eslint-disable no-param-reassign */
144145
if (node.type === "Element" && node.name.startsWith("react:")) {
145146
const tag = node as Element;
146-
const component = tag.name.slice(6);
147+
const componentExpression = tag.name.slice(6);
148+
const alias = `React$${componentExpression.replace(/\./g, "$")}`;
147149
const tagStart = node.start;
148150
const tagEnd = node.end;
149151
const closeStart = tagEnd - tag.name.length - 3;
150-
content.overwrite(tagStart + 1, tagStart + 7, "React$");
151-
if (content.slice(closeStart, closeStart + 8) === `</react:`) {
152-
content.overwrite(closeStart + 2, closeStart + 8, `React$`);
152+
const hasCloseTag =
153+
content.slice(closeStart, closeStart + 8) === `</react:`;
154+
content.overwrite(tagStart + 1, tagStart + 1 + tag.name.length, alias);
155+
if (hasCloseTag) {
156+
content.overwrite(
157+
closeStart + 2,
158+
closeStart + 2 + tag.name.length,
159+
alias
160+
);
153161
}
154-
if (components.includes(component) === false) {
155-
components.push(component);
162+
if (!components[alias]) {
163+
components[alias] = componentExpression;
156164
}
157165
tag.attributes.forEach((attr) => {
158166
if (attr.type === "EventHandler") {

src/tests/__snapshots__/preprocess.spec.ts.snap

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,20 @@ const React$Alert = React$$sveltify(Alert, React$$createPortal, React$$ReactDOM,
7272
"
7373
`;
7474

75+
exports[`svelte-preprocess-react > should process <react:Context.Provider> tags 1`] = `
76+
"<script lang=\\"ts\\">import React$$sveltify from \\"svelte-preprocess-react/sveltify\\"; import React$$ReactDOM from \\"react-dom/client\\"; import { createPortal as React$$createPortal} from \\"react-dom\\"; import { renderToString as React$$renderToString } from \\"react-dom/server\\"; import used from \\"$lib/used\\";
77+
export let Context;
78+
used(Context);
79+
const React$Context$Provider = React$$sveltify(Context.Provider, React$$createPortal, React$$ReactDOM, React$$renderToString);</script>
80+
81+
<React$Context$Provider children=\\"content\\" />
82+
83+
<React$Context$Provider>
84+
<button>ok</button>
85+
</React$Context$Provider>
86+
"
87+
`;
88+
7589
exports[`svelte-preprocess-react > should process <react:component> tags 1`] = `
7690
"<script>import React$$sveltify from \\"svelte-preprocess-react/sveltify\\"; import React$$ReactDOM from \\"react-dom/client\\"; import { createPortal as React$$createPortal} from \\"react-dom\\"; import { renderToString as React$$renderToString } from \\"react-dom/server\\";
7791
// @ts-nocheck

src/tests/fixtures/Provider.svelte

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
<script lang="ts">
2+
import used from "$lib/used";
3+
import type { Context as ContentType } from "react";
4+
5+
export let Context: ContentType<any>;
6+
7+
used(Context);
8+
</script>
9+
10+
<react:Context.Provider>content</react:Context.Provider>
11+
12+
<react:Context.Provider>
13+
<button>ok</button>
14+
</react:Context.Provider>

src/tests/preprocess.spec.ts

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,17 @@ describe("svelte-preprocess-react", () => {
9292
);
9393
expect(output.code).toMatchSnapshot();
9494
});
95+
96+
it("should process <react:Context.Provider> tags", async () => {
97+
const filename = resolveFilename("./fixtures/Provider.svelte");
98+
const src = await readFile(filename, "utf8");
99+
const output = await preprocess(
100+
src,
101+
preprocessReact({ preprocess: sveltePreprocess() }),
102+
{ filename }
103+
);
104+
expect(output.code).toMatchSnapshot();
105+
});
95106
});
96107

97108
const base = dirname(import.meta.url).replace("file://", "");

0 commit comments

Comments
 (0)