-
Notifications
You must be signed in to change notification settings - Fork 7
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Bob Fanger
committed
Jun 9, 2022
0 parents
commit 59b7ed1
Showing
29 changed files
with
3,651 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
defaults |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
/node_modules | ||
/build | ||
/.svelte-kit |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
{ | ||
"extends": ["triple/svelte"], | ||
"env": { | ||
"browser": true, | ||
"node": true | ||
}, | ||
"parser": "@typescript-eslint/parser", | ||
"parserOptions": { | ||
"project": "./tsconfig.eslint.json", | ||
"extraFileExtensions": [".cjs", ".svelte"] | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
.DS_Store | ||
node_modules | ||
/.svelte-kit | ||
/build | ||
/package | ||
/functions | ||
/storybook-static | ||
/test-results | ||
.env |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
#!/bin/sh | ||
. "$(dirname "$0")/_/husky.sh" | ||
|
||
npx lint-staged |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
#!/bin/sh | ||
. "$(dirname "$0")/_/husky.sh" | ||
|
||
npm run test |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
/.svelte-kit | ||
/build | ||
/package | ||
/node_modules |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,46 @@ | ||
# Svelte Preprocess React | ||
|
||
Seamlessly use React components inside a Svelte app | ||
|
||
# "Embrace, extend, and extinguish" | ||
|
||
This preprocessor is intended as temporary solution when migrating an existing large React codebase. | ||
The goal should be to rewrite all the components to Svelte and remove this preprocessor from your setup. | ||
|
||
## Usage | ||
|
||
```html | ||
<script> | ||
import MyReactComponent from "./MyReactComponent.jsx"; | ||
</script> | ||
|
||
<react:MyReactComponent /> | ||
``` | ||
|
||
## Setup | ||
|
||
```js | ||
// svelte.config.js | ||
import preprocessReact from "svelte-preprocess-react"; | ||
|
||
export default { | ||
preprocess: preprocessReact(), | ||
}; | ||
``` | ||
|
||
or when used in combination with svelte-preprocess: | ||
|
||
```js | ||
// svelte.config.js | ||
import preprocess from "svelte-preprocess"; | ||
import preprocessReact from "svelte-preprocess-react"; | ||
|
||
export default { | ||
preprocess: [preprocess({ sourceMap: true }), preprocessReact()], | ||
}; | ||
``` | ||
|
||
## Ideas / Roadmap | ||
|
||
- Auto insert `<react:` for .tsx and .jsx imports. | ||
- Research if it's possible to reliably determine if a Component is a React component at compile time. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,77 @@ | ||
{ | ||
"name": "svelte-preprocess-react", | ||
"version": "0.1.0", | ||
"license": "MIT", | ||
"type": "module", | ||
"scripts": { | ||
"dev": "svelte-kit dev", | ||
"build": "svelte-kit build", | ||
"preview": "svelte-kit preview", | ||
"package": "svelte-kit package", | ||
"lint": "concurrently -c \"#c596c7\",\"#676778\",\"#3074c0\",\"#7c7cea\" --kill-others-on-fail \"npm:lint:*\"", | ||
"lint:prettier": "prettier --check --loglevel=warn \"src/**/*.svelte\"", | ||
"lint:svelte-check": "svelte-check --fail-on-warnings --fail-on-hints --ignore build,package", | ||
"lint:tsc": "tsc --noEmit", | ||
"lint:eslint": "eslint --ext=js,ts,svelte --max-warnings=0 src", | ||
"format": "prettier --write . && eslint --ext=js,ts,svelte --fix src", | ||
"prepare": "husky install", | ||
"test": "vitest run --passWithNoTests", | ||
"vitest": "vitest watch" | ||
}, | ||
"prettier": "eslint-config-triple/.prettierrc", | ||
"lint-staged": { | ||
"*.ts": [ | ||
"eslint --max-warnings 0 --no-ignore", | ||
"sh -c 'tsc -p tsconfig.json --noEmit'" | ||
], | ||
"*.(c)?js": [ | ||
"eslint --max-warnings 0 --no-ignore" | ||
], | ||
"*.svelte": [ | ||
"eslint --max-warnings 0 --no-ignore", | ||
"svelte-check --fail-on-warnings --fail-on-hints", | ||
"prettier --check" | ||
] | ||
}, | ||
"devDependencies": { | ||
"@sveltejs/adapter-static": "next", | ||
"@sveltejs/kit": "next", | ||
"@testing-library/svelte": "^3.1.0", | ||
"@types/react": "^18.0.12", | ||
"@types/react-dom": "^18.0.5", | ||
"@typescript-eslint/eslint-plugin": "^5.27.0", | ||
"@typescript-eslint/parser": "^5.27.0", | ||
"autoprefixer": "^10.4.7", | ||
"concurrently": "^7.2.1", | ||
"eslint": "^8.16.0", | ||
"eslint-config-airbnb-base": "^15.0.0", | ||
"eslint-config-airbnb-typescript": "^17.0.0", | ||
"eslint-config-prettier": "^8.5.0", | ||
"eslint-config-triple": "^0.5.1", | ||
"eslint-import-resolver-typescript": "^2.7.1", | ||
"eslint-plugin-import": "^2.26.0", | ||
"eslint-plugin-only-warn": "^1.0.3", | ||
"eslint-plugin-prettier": "^4.0.0", | ||
"eslint-plugin-svelte3": "^4.0.0", | ||
"husky": "^8.0.1", | ||
"jsdom": "^19.0.0", | ||
"lint-staged": "^13.0.0", | ||
"postcss": "^8.4.14", | ||
"prettier": "^2.6.2", | ||
"prettier-plugin-svelte": "^2.7.0", | ||
"react": "^18.1.0", | ||
"react-dom": "^18.1.0", | ||
"sass": "^1.52.2", | ||
"svelte": "^3.48.0", | ||
"svelte-check": "^2.7.2", | ||
"svelte-preprocess": "^4.10.6", | ||
"svelte2tsx": "^0.5.10", | ||
"typescript": "^4.7.2", | ||
"vite": "^2.9.9", | ||
"vite-tsconfig-paths": "^3.4.1", | ||
"vitest": "^0.14.1" | ||
}, | ||
"dependencies": { | ||
"magic-string": "^0.26.2" | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
module.exports = { | ||
plugins: [require("autoprefixer")], | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
<!DOCTYPE html> | ||
<html> | ||
<head> | ||
<meta charset="utf-8" /> | ||
<link rel="icon" href="/favicon.ico" /> | ||
<meta name="viewport" content="width=device-width, initial-scale=1" /> | ||
%sveltekit.head% | ||
</head> | ||
<body> | ||
%sveltekit.body% | ||
</body> | ||
</html> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
import * as React from "react"; | ||
|
||
type Props = { | ||
initialValue: number; | ||
}; | ||
const Counter: React.FC<Props> = ({ initialValue = 0 }) => { | ||
const [count, setCount] = React.useState(initialValue); | ||
function decrease() { | ||
setCount(count - 1); | ||
} | ||
function increase() { | ||
setCount(count + 1); | ||
} | ||
return ( | ||
<> | ||
<button onClick={decrease}>-</button> | ||
{count} | ||
<button onClick={increase}>+</button> | ||
</> | ||
); | ||
}; | ||
export default Counter; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
/// <reference types="@sveltejs/kit" /> | ||
/// <reference types="svelte" /> | ||
/// <reference types="vite/client" /> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,41 @@ | ||
<script lang="ts"> | ||
import { onMount } from "svelte"; | ||
import React, { createElement } from "react"; | ||
import { createRoot, type Root } from "react-dom/client"; | ||
import { renderToString } from "react-dom/server"; | ||
export let ReactComponent: React.FC; | ||
const html = ReactComponent | ||
? renderToString(createElement(ReactComponent, $$props)) | ||
: ""; | ||
let el: Element; | ||
let root: Root | undefined; | ||
$: if (root && $$props) { | ||
rerender(); | ||
} | ||
onMount(() => { | ||
root = createRoot(el); | ||
rerender(); | ||
return () => { | ||
root?.unmount(); | ||
}; | ||
}); | ||
function rerender() { | ||
if (!root) { | ||
return; | ||
} | ||
root.render(createElement(ReactComponent, $$props)); | ||
} | ||
</script> | ||
|
||
<react-wrapper bind:this={el}>{@html html}</react-wrapper> | ||
|
||
<style> | ||
react-wrapper { | ||
display: contents; | ||
} | ||
</style> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
import type preprocessReact from "./svelte-preprocess-react"; | ||
|
||
export default preprocessReact; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,76 @@ | ||
import MagicString from "magic-string"; | ||
import { compile } from "svelte/compiler"; | ||
import type { | ||
Element, | ||
Script, | ||
TemplateNode, | ||
Transition, | ||
} from "svelte/types/compiler/interfaces"; | ||
import type { PreprocessorGroup } from "svelte/types/compiler/preprocess"; | ||
|
||
export default function preprocessReact(): PreprocessorGroup { | ||
// @todo Alternate import older React versions | ||
const importStatement = | ||
'import sveltifyReact from "svelte-preprocess-react/sveltifyReact18";'; | ||
|
||
return { | ||
markup: ({ content, filename }) => { | ||
const compiled = compile(content, { filename }); | ||
const refs: Refs = { offset: 0, components: [] }; | ||
const s = new MagicString(content, { filename }); | ||
replaceTags(compiled.ast.html, s, refs); | ||
|
||
if (refs.components.length === 0) { | ||
return { code: content }; | ||
} | ||
const script = compiled.ast.instance || (compiled.ast.module as Script); | ||
const offset = compiled.ast.html.start > script.start ? 0 : refs.offset; | ||
const jsEnd = script.content.end + offset; | ||
refs.components.forEach((component) => { | ||
const code = `const React$${component} = sveltifyReact(${component});`; | ||
s.appendRight(jsEnd, code); | ||
}); | ||
const jsStart = script.content.start + offset; | ||
s.appendRight(jsStart, importStatement); | ||
return { | ||
code: s.toString(), | ||
map: s.generateMap(), | ||
}; | ||
}, | ||
}; | ||
|
||
type Refs = { offset: number; components: string[] }; | ||
function replaceTags(node: TemplateNode, content: MagicString, refs: Refs) { | ||
/* eslint-disable no-param-reassign */ | ||
if (node.type === "Element" && node.name.startsWith("react:")) { | ||
const tag = node as Element; | ||
const component = tag.name.slice(6); | ||
const tagStart = node.start + refs.offset; | ||
content.overwrite(tagStart + 1, tagStart + 7, "React$"); | ||
if (refs.components.includes(component) === false) { | ||
refs.components.push(component); | ||
} | ||
tag.attributes.forEach((attr) => { | ||
if (attr.type === "EventHandler") { | ||
const event = attr as Transition; // the BaseExpressionDirective is not exposed directly | ||
if (event.modifiers.length > 0) { | ||
throw new Error( | ||
"event modifier are not (yet) supported for React components" | ||
); | ||
} | ||
const eventStart = event.start + refs.offset; | ||
content.overwrite( | ||
eventStart, | ||
eventStart + 4, | ||
`on${event.name[0].toUpperCase()}` | ||
); | ||
|
||
refs.offset -= 1; | ||
} | ||
}); | ||
} | ||
node.children?.forEach((child) => { | ||
replaceTags(child, content, refs); | ||
}); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,32 @@ | ||
import type { ComponentClass, FunctionComponent } from "react"; | ||
import ReactWrapper from "./React18Wrapper.svelte"; | ||
|
||
export default function sveltifyReact<P>( | ||
ReactComponent: FunctionComponent<P> | ComponentClass<P> | ||
): (props: P) => any { | ||
const ssr = typeof (ReactWrapper as any).$$render === "function"; | ||
if (ssr) { | ||
const { $$render } = ReactWrapper as any; | ||
return { | ||
...ReactWrapper, | ||
$$render(meta: any, props: any, ...args: any[]) { | ||
const result = $$render.call( | ||
ReactWrapper, | ||
meta, | ||
{ ReactComponent, ...props }, | ||
...args | ||
); | ||
return result; | ||
}, | ||
} as any; | ||
} | ||
|
||
function Sveltified(options: any) { | ||
const component = new ReactWrapper({ | ||
...options, | ||
props: { ReactComponent, ...options.props }, | ||
}); | ||
return component; | ||
} | ||
return Sveltified as any; | ||
} |
Oops, something went wrong.