Skip to content

Commit

Permalink
feat: Added support for react elements
Browse files Browse the repository at this point in the history
Fixes #13
  • Loading branch information
Bob Fanger committed Sep 24, 2022
1 parent 13137d5 commit 0124340
Show file tree
Hide file tree
Showing 9 changed files with 39 additions and 12 deletions.
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
"type": "git",
"url": "https://github.com/bfanger/svelte-preprocess-react.git"
},
"version": "0.10.0",
"version": "0.11.0",
"license": "MIT",
"type": "module",
"scripts": {
Expand Down
2 changes: 1 addition & 1 deletion playwright/tests/hooks.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { test, expect } from "@playwright/test";
test.use({ viewport: { width: 480, height: 360 } });
test.describe("hooks", () => {
test("counter", async ({ page }) => {
await page.goto("/hooks");
await page.goto("/hooks", { waitUntil: "networkidle" });
await expect(page.locator('[data-testid="count"]')).toHaveText("0");
await page.locator('[data-testid="add"]').click();
await expect(page.locator('[data-testid="count"]')).toHaveText("1");
Expand Down
4 changes: 0 additions & 4 deletions src/lib/internal/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,6 @@ import type React from "react";
import type { ComponentClass, FunctionComponent } from "react";
import type { Readable, Writable } from "svelte/store";

export type ConstructorOf<T> = {
new (): T;
};

export type HandlerName<T extends string> = `on${Capitalize<T>}`;
export type EventName<T extends string> = T extends `on${infer N}`
? Uncapitalize<N>
Expand Down
8 changes: 6 additions & 2 deletions src/lib/preprocessReact.ts
Original file line number Diff line number Diff line change
Expand Up @@ -125,7 +125,7 @@ function transform(content: string, options: TransformOptions) {
.join(";");

if (!script) {
s.prepend(`<script>\n${imports}\n\n${wrappers}\n</script>\n\n`);
s.prepend(`<script>\n${imports.join("; ")}\n\n${wrappers}\n</script>\n\n`);
} else {
s.appendRight(script.content.end, wrappers);
s.appendRight(script.content.start, `${imports.join("; ")}; `);
Expand Down Expand Up @@ -160,7 +160,11 @@ function replaceReactTags(
);
}
if (!components[alias]) {
components[alias] = componentExpression;
if (componentExpression.match(/^[a-z-]+$/)) {
components[alias] = `"${componentExpression}"`;
} else {
components[alias] = componentExpression;
}
}
tag.attributes.forEach((attr) => {
if (attr.type === "EventHandler") {
Expand Down
10 changes: 7 additions & 3 deletions src/lib/sveltify.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import type { ComponentClass, FunctionComponent } from "react";
import type { SvelteComponentTyped } from "svelte/internal";
import type ReactDOMServer from "react-dom/server";
import { writable, type Readable } from "svelte/store";
import type { ConstructorOf, SvelteInit, TreeNode } from "./internal/types";
import type { SvelteInit, TreeNode } from "./internal/types";
import ReactWrapper from "./internal/ReactWrapper.svelte";
import Slot from "./internal/Slot.svelte";
import Bridge, { type BridgeProps } from "./internal/Bridge.js";
Expand All @@ -23,7 +23,11 @@ const tree: TreeNode = {
hooks: writable([]),
};

type Sveltified<P> = ConstructorOf<SvelteComponentTyped<Omit<P, "children">>>;
declare type Sveltified<P extends Record<string, any>> = new (args: {
target: any;
props?: P;
}) => SvelteComponentTyped<P>;

/**
* Convert a React component into a Svelte component.
*/
Expand All @@ -32,7 +36,7 @@ export default function sveltify<P>(
createPortal: BridgeProps["createPortal"],
ReactDOMClient: any,
renderToString?: typeof ReactDOMServer.renderToString
): Sveltified<P> {
): Sveltified<Omit<P, "children">> {
const Wrapper = ReactWrapper as any;
const ssr = typeof Wrapper.$$render === "function";
if (ssr) {
Expand Down
1 change: 1 addition & 0 deletions src/routes/preprocessor/+page.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -17,3 +17,4 @@
"Multiline content". {10 ** 4} Lorem ipsum dolor sit amet consectetur adipisicing
elit. Suscipit nisi atque asperiores.</react:Alert
>
<react:div>a div</react:div>
15 changes: 14 additions & 1 deletion src/tests/__snapshots__/preprocess.spec.ts.snap
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ const React$Clicker = React$$sveltify(Clicker, React$$createPortal, React$$React

exports[`svelte-preprocess-react > should inject a script tag 1`] = `
"<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\\"
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\\"
const React$Counter = React$$sveltify(Counter, React$$createPortal, React$$ReactDOM, React$$renderToString);
</script>
Expand Down Expand Up @@ -132,6 +132,19 @@ const React$Clicker = React$$sveltify(Clicker, React$$createPortal, React$$React
"
`;

exports[`svelte-preprocess-react > should process <react:element> (lowercase) tags 1`] = `
"<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\\"
const React$button = React$$sveltify(\\"button\\", React$$createPortal, React$$ReactDOM, React$$renderToString);
</script>
<React$button onClick={() => console.info(\\"clicked\\")}>
<slot />
</React$button>
"
`;

exports[`svelte-preprocess-react > should support typescript when using preprocess 1`] = `
"<script lang=\\"ts\\">export let title;
</script>
Expand Down
3 changes: 3 additions & 0 deletions src/tests/fixtures/Element.svelte
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
<react:button on:click={() => console.info("clicked")}>
<slot />
</react:button>
6 changes: 6 additions & 0 deletions src/tests/preprocess.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,12 @@ describe("svelte-preprocess-react", () => {
);
expect(output.code).toMatchSnapshot();
});
it("should process <react:element> (lowercase) tags", async () => {
const filename = resolveFilename("./fixtures/Element.svelte");
const src = await readFile(filename, "utf8");
const output = await preprocess(src, preprocessReact(), { filename });
expect(output.code).toMatchSnapshot();
});
});

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

0 comments on commit 0124340

Please sign in to comment.