Skip to content

Commit cc2397d

Browse files
committed
v-0.0.15
1 parent d3ca60b commit cc2397d

18 files changed

Lines changed: 323 additions & 93 deletions

.vscode/settings.json

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
{
2+
"cSpell.words": [
3+
"undestructure"
4+
]
5+
}

exp.cjs

Lines changed: 0 additions & 19 deletions
This file was deleted.

jsconfig.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,4 +4,4 @@
44
"target": "es6"
55
},
66
"exclude": ["node_modules"]
7-
}
7+
}

package.json

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,14 @@
11
{
22
"name": "babel-plugin-solid-undestructure",
33
"description": "A Babel plugin for SolidJS that allows you to destructure component props without losing reactivity.",
4-
"version": "0.0.14",
4+
"version": "0.0.15",
55
"main": "src/index.cjs",
66
"module": "src/index.js",
77
"types": "src/index.d.ts",
88
"type": "module",
99
"scripts": {
10-
"test": "uvu tests"
10+
"test": "uvu tests",
11+
"playground": "node playground.cjs"
1112
},
1213
"peerDependencies": {
1314
"solid-js": "^1.2.4"

playground.cjs

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
const { transformAsync } = require("@babel/core")
2+
3+
4+
// Change the following code and and run `npm run playground`
5+
const src=`import { Component } from 'solid-js'
6+
import x from 'babel-plugin-solid-undestructure'
7+
const MyComp: Component<T> = ({ a, b, c, ...other }) => {a; b; c; other;}`
8+
9+
10+
;(async () => {
11+
const res = await transformAsync(
12+
src,
13+
{ plugins: [
14+
["@babel/plugin-syntax-typescript", { isTSX: true }],
15+
"./src/index.cjs"
16+
] }
17+
)
18+
19+
console.log(res.code)
20+
})()

readme.md

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,8 @@ const MyComp: Component<...> = props => {
7272

7373
See also [undestructure-example](https://github.com/orenelbaum/undestructure-example).
7474

75-
This plugin is still in early development and still has some bugs.
75+
This plugin doesn't have any known bugs at the moment. I'm not sure if it's ready for production yet but it probably will be soon. If you encounter any bugs please open an issue.
76+
7677

7778
## `Component` type annotation
7879

@@ -194,6 +195,6 @@ With this configuration you can use both the `Component` type and the `component
194195

195196
## Other cool plugins for Solid:
196197

197-
- https://github.com/orenelbaum/babel-plugin-reactivars-solid - Svelte like "reactive variables" for Solid that lets you pass reactive variables (getter + setter) around in a concise way (also made by me).
198-
- https://github.com/LXSMNSYC/babel-plugin-solid-labels - Solid labels is more of an all in one plugin. It has reactive variables, prop destructuring (like this plugin) and some more stuff.
198+
- https://github.com/orenelbaum/babel-plugin-reactivars-solid - A Svelte-like "reactive variables" plugin for Solid that lets you pass reactive variables (getter + setter) around in a concise way (also made by me).
199+
- https://github.com/LXSMNSYC/babel-plugin-solid-labels - Solid labels is more of an all in one plugin. It has Svelte-like reactive variables, prop destructuring (like this plugin) and more.
199200
- https://github.com/LXSMNSYC/solid-sfc - An experimental SFC compiler for SolidJS.

src/check-func/check-ctf-annotation.cjs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
const { getProgram } = require("../utils.cjs")
12

23
/**
34
* Checks that the function is annotated with the `component` CTF.
@@ -6,14 +7,15 @@ function checkCtfAnnotation(path, state) {
67
if (path.parent?.type !== "CallExpression") return false
78

89
const wrappingFunctionName = path.parent.callee.name
9-
const bindings = path.context.scope.bindings
10+
const bindings = getProgram(path).scope.bindings
1011
const wrappingFunctionBinding = bindings[wrappingFunctionName]
1112
if (!wrappingFunctionBinding) return false
1213
const importSpecifier = wrappingFunctionBinding.path.node
1314
if (importSpecifier.type !== "ImportSpecifier") return false
1415
if (importSpecifier.imported.name !== "component") return false
1516
if (wrappingFunctionBinding.path.parent.source.value !== 'babel-plugin-solid-undestructure') return false
1617

18+
1719
state.isAnnotatedWithCtf = true
1820
state.annotatingCtfBinding = wrappingFunctionBinding
1921

src/check-func/check-func.cjs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ const checkFirstParam = path => {
2929
* If the function is annotated with a CTF, mark it in the state.
3030
*/
3131
const checkFunc = (funcPath, opts, state) => {
32+
// Make sure the function wasn't already transformed.
3233
if (funcPath.transformed) return false
3334

3435
if (!checkFuncAnnotation(opts, funcPath, state)) return { funcAnnotation: false }

src/func-visitor.cjs

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
const { validateFunc } = require("./validate-func.cjs")
2+
const { checkFunc } = require("./check-func/check-func.cjs")
3+
const { getPropsInfo } = require("./get-props-info.cjs")
4+
const { removeWrappingCtf } = require("./remove-wrapping-ctf.cjs")
5+
const { addMergePropsCall } = require("./add-merge-props-call.cjs")
6+
const { transformPropsParam } = require("./transform-props-param.cjs")
7+
const { createNewPropsIdentifier } = require("./create-new-props-identifier.cjs")
8+
const { transformPropReferences } = require("./transform-prop-references.cjs")
9+
const { handleRestElement } = require("./handle-rest-element.cjs")
10+
11+
12+
const funcVisitor = (funcPath, { opts }) => {
13+
const state = {}
14+
15+
// Check that the function needs to be transformed.
16+
const checkRes = checkFunc(funcPath, opts, state)
17+
18+
if (!checkRes?.funcAnnotation) return
19+
20+
removeWrappingCtf(funcPath, state)
21+
22+
if (!checkRes.propDestructuring) return
23+
24+
// Validate that the function doesn't use unsupported syntax.
25+
validateFunc(funcPath)
26+
27+
getPropsInfo(funcPath, state)
28+
29+
// Create a unique props identifier and store it in state.
30+
createNewPropsIdentifier(funcPath, state)
31+
32+
addMergePropsCall(funcPath, state)
33+
34+
handleRestElement(funcPath, state)
35+
36+
transformPropReferences(funcPath, state)
37+
38+
transformPropsParam(funcPath, state)
39+
40+
funcPath.transformed = true
41+
}
42+
43+
module.exports = { funcVisitor }
Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
2+
/**
3+
* Checks if there are any remaining imports from `babel-plugin-solid-undestructure`.
4+
* If there are any remaining imports and any of them are used, an error is thrown.
5+
* Otherwise, if none are used, the remaining imports are removed.
6+
*/
7+
const handleRemainingPluginImports = programPath => {
8+
const pluginImportPaths = getPluginImportPaths(programPath)
9+
10+
if (pluginImportPaths.length > 0) {
11+
const bindings = programPath.scope.bindings
12+
13+
let someImportIsUsed = checkIfAnyImportsAreUsed(pluginImportPaths, bindings)
14+
15+
if (someImportIsUsed) {
16+
throw new Error(
17+
`babel-plugin-undestructure error: An import from 'babel-plugin-undestructure' remained after applying the transformation.
18+
This is either a configuration problem or a bug in the plugin.
19+
If the plugin is configured correctly, please open an issue on GitHub.`
20+
)
21+
}
22+
23+
// Remove the import declarations.
24+
for (const importDeclarationPath of pluginImportPaths)
25+
importDeclarationPath.remove()
26+
}
27+
}
28+
29+
function checkIfAnyImportsAreUsed(pluginImportPaths, bindings) {
30+
let someImportIsUsed = false
31+
32+
for (const importDeclarationPath of pluginImportPaths){
33+
const importDeclaration = importDeclarationPath.node
34+
for (const specifier of importDeclaration.specifiers)
35+
if (bindings[specifier.local.name].references >= 1)
36+
someImportIsUsed = true
37+
}
38+
39+
return someImportIsUsed
40+
}
41+
42+
function getPluginImportPaths(programPath) {
43+
const bodyLength = programPath.node.body.length
44+
const pluginImportPaths = []
45+
46+
for (let i = 0; i < bodyLength; i++) {
47+
const node = programPath.node.body[i]
48+
49+
if (
50+
node.type === 'ImportDeclaration'
51+
&& node.source.value === 'babel-plugin-solid-undestructure'
52+
)
53+
pluginImportPaths.push(programPath.get(`body.${i}`))
54+
}
55+
56+
return pluginImportPaths
57+
}
58+
59+
module.exports.handleRemainingPluginImports = handleRemainingPluginImports

0 commit comments

Comments
 (0)