Skip to content

Commit

Permalink
doc: Improved error messages
Browse files Browse the repository at this point in the history
  • Loading branch information
bfanger committed Oct 20, 2024
1 parent e10c463 commit 7ca93df
Show file tree
Hide file tree
Showing 6 changed files with 45 additions and 30 deletions.
25 changes: 11 additions & 14 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,26 +13,23 @@ Supports:

This project was featured at the [Svelte London - November 2022 Meetup](https://www.youtube.com/live/DXQl1G54DJY?feature=share&t=2569)

# "Embrace, extend and extinguish"
> "Embrace, extend and extinguish"
This preprocessor is intended as temporary solution when migrating an existing large React codebase or when a third-party hasn't yet provided a Svelte adapter.
After you've gradually converted all components to Svelte you can remove this preprocessor from your setup.
This preprocessor is intended as solution using third-party React components or for migrating an existing React codebase.

## Using React inside Svelte components

> Embrace
Inside the Svelte template prepend the name of the component with `react.` prefix.

Instead of `<Button>`, you'd write `<react.Button>`

You're also able to use libraries from the react ecosystem, react-youtube for example:
Use libraries from the React's ecosystem, react-youtube for example:

```svelte
<script>
import YouTube from "react-youtube";
const react = sveltify({ YouTube }); // Optional, but improves tooling
const react = sveltify({ YouTube }); // Optional step, but adds type-safety
</script>
<react.YouTube videoId="AdNJ3fydeao" />
Expand All @@ -58,7 +55,7 @@ The snippet above would be generate:
<react.YouTube videoId="AdNJ3fydeao" />
```

## Setup
## Setup / Installation

```sh
npm install svelte-preprocess-react
Expand All @@ -79,7 +76,7 @@ When using other processors like [@sveltejs/vite-plugin-svelte](https://github.c

```js
// svelte.config.js
import { vitePreprocess } from "@sveltejs/kit/vite";
import { vitePreprocess } from "@sveltejs/vite-plugin-svelte";
import preprocessReact from "svelte-preprocess-react/preprocessReact";

export default {
Expand All @@ -89,8 +86,6 @@ export default {

## Using Svelte inside React components

> Extend
Once you've converted a React component to Svelte, you'd want delete that React component, but some if other React components depended on that component you can use `reactify` to use the new Svelte component as a React component.

```jsx
Expand All @@ -106,15 +101,17 @@ function MyComponent() {

## Using multiple frameworks is a bad idea

> Extinguish
Using multiple frontend frameworks adds overhead, both in User and Developer experience.

- Increased download size
- Slower (each framework boundary adds overhead)
- Context switching, keeping the intricacies of both Svelte and React in your head slows down development

svelte-preprocess-react is a migration tool, it can be used to migrate _from_ or _to_ React, it's not a long term solution.
When using third-party React components, keep an eye out for Svelte alternatives, or publish your own.

When used as migration tool (can be used to migrate _from_ or _to_ React),
the goal should be to stop writing new React components, and to convert existing React components to Svelte components.
Once all components are converted this preprocessor should be uninstalled.

# More info

Expand Down
26 changes: 17 additions & 9 deletions docs/migration-to-2.0.md
Original file line number Diff line number Diff line change
@@ -1,28 +1,36 @@
# Migration to 2.0

Change `<react:MyComponent>` into `<react.MyComponent>` (`:` to `.`).
In the tag change the `:` double colon into a `.` dot, instead of:

When using Typescript, add:
`<react:MyComponent>` ❌ old

write:

`<react.MyComponent>` ✅ new

## Type safety

When using Typescript, in the `<script lang="ts">` section add:

```ts
const react = sveltify({ MyComponent });
```

in the `<script lang="ts">` section for type safety.
## ESLint

When getting ESLint no-undef errors:
The preprocessor will autoimport sveltify and can also generate the react object based on usage of `<react.* />` tags.

in `eslint.config.js` add `sveltify: true` to your globals or add a `import { sveltify } from 'svelte-preprocess-react'`.
So both `const react = sveltify({ MyComponent })` and the `import { sveltify } from "svelte-preprocess-react"` are optional, but that confuses ESLint.

Also add `react: true` if you don't want
To avoid the `no-undef` errors in your `eslint.config.js` add `sveltify: true, react: true` to your `globals`.
When using Typescript it's recommended to only add `sveltify: true`, then the eslint warnign acts as a reminder to add a `const react = sveltify({..})` for type-safety.

## Why the change?

In Svelte 5 the compiler gives a warning when using `<react:MyComponent />` syntax:

> Self-closing HTML tags for non-void elements are ambiguous — use `<react:MyComponent ...></react:MyComponent>` rather than `<react:MyComponent ... />`(element_invalid_self_closing_tag)
Easily solved, but it a less elegant syntax.

Secondly, the new syntax allows for IDE support.
Easily solved by adding a closing tag, but it's a less elegant syntax.

Secondly, a huge benefit of the new rune-inspired syntax is that it's compatible with existing tooling.
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": "2.0.0-next.8",
"version": "2.0.0",
"license": "MIT",
"type": "module",
"scripts": {
Expand Down
18 changes: 14 additions & 4 deletions src/lib/preprocessReact.js
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,7 @@ function transform(content, options) {
modern: false,
});
const s = new MagicString(content, { filename: options.filename });
const components = replaceReactTags(ast.html, s);
const components = replaceReactTags(ast.html, s, options.filename);
const aliases = Object.entries(components);

let depsInjected = false;
Expand Down Expand Up @@ -197,16 +197,26 @@ function transform(content, options) {
*
* @param {any} node
* @param {MagicString} content
* @param {string | undefined} filename
* @param {Record<string, { dispatcher: boolean }>} components
*/
function replaceReactTags(node, content, components = {}) {
function replaceReactTags(node, content, filename, components = {}) {
if (
(node.type === "Element" && node.name.startsWith("react:")) ||
(node.type === "InlineComponent" && node.name.startsWith("react."))
) {
let legacy = node.name.startsWith("react:");
if (legacy) {
console.warn("'<react:*' syntax is deprecated, use '<react.*'");
let location = "";
if (filename) {
location += ` in ${filename}`;
}
if (node.start) {
location += ` on line ${content.original.substring(0, node.start).split("\n").length}`;
}
console.warn(
`'<${node.name}' syntax is deprecated, use '<react.${node.name.substring(6)}'${location}.\nhttps://github.com/bfanger/svelte-preprocess-react/blob/main/docs/migration-to-2.0.md\n`,
);
content.overwrite(node.start + 6, node.start + 7, ".");
const tagEnd = node.end - node.name.length - 3;
if (content.slice(tagEnd, tagEnd + 8) === `</react:`) {
Expand Down Expand Up @@ -281,7 +291,7 @@ function replaceReactTags(node, content, components = {}) {
* @param {any} child
*/
function processChild(child) {
replaceReactTags(child, content, components);
replaceReactTags(child, content, filename, components);
}
// traverse children & branching blocks
node.children?.forEach(processChild);
Expand Down
2 changes: 1 addition & 1 deletion src/lib/used.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

/**
* @deprecated
* Stop using used() to silence linting & typescript errors, and add:
* Stop using used() to silence linting & typescript errors, instead:
* ```ts
* const react = sveltity({ MyComponent });
* ```
Expand Down
2 changes: 1 addition & 1 deletion src/routes/preprocessor/+page.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@

<react.Counter initial={25} onCount={console.info} />

<react.Alert>A simple alert</react.Alert>
<react:Alert>A simple alert</react:Alert>

<react.Alert>
"Multiline content". {10 ** 4} Lorem ipsum dolor sit amet consectetur adipisicing
Expand Down

0 comments on commit 7ca93df

Please sign in to comment.