All Projects → RIP21 → babel-plugin-hyperscript-to-jsx

RIP21 / babel-plugin-hyperscript-to-jsx

Licence: MIT license
This plugin transforms react-hyperscript into JSX. Intended to be used as codemod.

Programming Languages

javascript
184084 projects - #8 most used programming language

Projects that are alternatives of or similar to babel-plugin-hyperscript-to-jsx

Babel Plugin Transform Incremental Dom
Turn JSX into IncrementalDOM
Stars: ✭ 146 (+630%)
Mutual labels:  jsx, babel-plugin
Htm
Hyperscript Tagged Markup: JSX alternative using standard tagged templates, with compiler support.
Stars: ✭ 7,299 (+36395%)
Mutual labels:  jsx, babel-plugin
nornj
More exciting JS/JSX based on Template Engine, support control flow tags, custom directives, two-way binding, filters and custom operators.
Stars: ✭ 97 (+385%)
Mutual labels:  jsx, babel-plugin
Sowing Machine
🌱A React UI toolchain & JSX alternative
Stars: ✭ 64 (+220%)
Mutual labels:  jsx, babel-plugin
Babel Plugin React Persist
Automatically useCallback() & useMemo(); memoize inline functions
Stars: ✭ 91 (+355%)
Mutual labels:  jsx, babel-plugin
Jsx Control Statements
Neater If and For for React JSX
Stars: ✭ 1,305 (+6425%)
Mutual labels:  jsx, babel-plugin
Babel Plugin Jsx Two Way Binding
🍺 A two-way data binding solution for React
Stars: ✭ 15 (-25%)
Mutual labels:  jsx, babel-plugin
Babel Plugin Jsx Adopt
Stars: ✭ 94 (+370%)
Mutual labels:  jsx, babel-plugin
Babel Plugin React Html Attrs
Babel plugin which transforms HTML and SVG attributes on JSX host elements into React-compatible attributes
Stars: ✭ 170 (+750%)
Mutual labels:  jsx, babel-plugin
core
Server side rendering with The Elm Architecture in Deno
Stars: ✭ 16 (-20%)
Mutual labels:  jsx
React-Netflix-Clone
A Fully Responsive clone of Netflix website built using React.JS as a Front-end & Firebase as a Back-end.
Stars: ✭ 91 (+355%)
Mutual labels:  jsx
string-dom
Create HTML strings using JSX (or functions).
Stars: ✭ 13 (-35%)
Mutual labels:  jsx
ember-data-codemod
A codemod to upgrade to new ember-data packages
Stars: ✭ 13 (-35%)
Mutual labels:  codemod
vue3-jd-h5
🔥 Based on vue3.0.0, vant3.0.0, vue-router v4.0.0-0, vuex^4.0.0-0, vue-cli3, mockjs, imitating Jingdong Taobao, mobile H5 e-commerce platform! 基于vue3.0.0 ,vant3.0.0,vue-router v4.0.0-0, vuex^4.0.0-0,vue-cli3,mockjs,仿京东淘宝的,移动端H5电商平台!
Stars: ✭ 660 (+3200%)
Mutual labels:  jsx
ios-scriptable-tsx
在 vscode 上使用 typescript 和 jsx 开发 ios 小组件的小框架.基于 Scriptable app.
Stars: ✭ 113 (+465%)
Mutual labels:  jsx
babel-plugin-rewire-exports
Babel plugin for stubbing [ES6, ES2015] module exports
Stars: ✭ 62 (+210%)
Mutual labels:  babel-plugin
hexo-component-inferno
A collection of Inferno.js layout components and utility scripts for Hexo
Stars: ✭ 20 (+0%)
Mutual labels:  jsx
role-based-access-control
Role-based authorization || Role-based access-control in React.js
Stars: ✭ 111 (+455%)
Mutual labels:  jsx
react-jsx-renderer
A React component for Rendering JSX
Stars: ✭ 43 (+115%)
Mutual labels:  jsx
crud-app
❄️ A simple and beautiful CRUD application built with React.
Stars: ✭ 61 (+205%)
Mutual labels:  jsx

babel-plugin-hyperscript-to-jsx (codmod usage)

npm version

It's a quite complex codemod to migrate from hyperscript to JSX.

Code Before:
import h from "react-hyperscript";

import hx from "shit"

const StatelessComponent = props => h("h1");

const StatelessWithReturn = props => {
  return h(".class");
};

function HyperscriptAsRegularFunction(props) {
  return h("h1");
}

const HyperscriptAsVariable = h("div.lol", {
  someProp: "lol"
});

const HyperscriptWithExpressionAsChildren = h(
  AnotherComponent,
  { foo: "bar", bar: () => ({}), shouldRender: thing.length > 0 },
  [arr.map(() => h('h1'))]
)

// Should be ignored from transforming
const FirstArgTemplateLiteralWithComputedExpressions = h(`div.lol${stuff}`, {
  someProp: "lol"
});

// Not computed so should be fine
const FirstArgTemplateLiteral = h(`div.lol`, {
  someProp: "lol"
});

// Should be ignored
const WhenFirstArgumentIsFunctionThatIsCalled = () => h(getLoadableAnimation('pageCareersDeliver'), [h(fn())])

const ComputedRootWithObjectPropertyDeclaration = () =>
  h(
    ANIMATIONS[country],
    {
      className: "lol",
      content: h(".selectItem", [
        h("div", label),
        h(".flag", [
          h(RoundFlag, {
            mix: "flag",
            size: "xs",
            code: currencyData.countryCode
          }),
          // Computed not root should be wrapped in {}
          h(ANIMATIONS[country], { className: "lol" })
        ])
      ])
    },
    [h(ANIMATIONS[country], { className: "lol" }), h("h1"), kek && mem, surreal ? lol : kek, t.tabName, lol, <div/>]
  );

const ThirdArgOnIgnoredIsNotArray = () =>
  h(
    ANIMATIONS[country],
    {
      className: "lol",
    },
    // This first children in array will be ignored FOR THIS UGLY HACK IN INDEX
    children
  );

h(isCanada ? doStuff : doAnotherStuff, { someProp: true })
h('div', isCanada ? someProps : anotherProps)
h('div', isCanada ? someProps : anotherProps, "SomeChildren")

const SecondArgOnIgnoredIsNotArray = () =>
  h(ANIMATIONS[country], children);

const MultiMemberExpressionWithClosingTag = () => h(Pricing.lol.kek, { className }, [ h('h1') ])

// to handle h(Abc, { [kek]: 0, ["norm"]: 1 }) to < Abc {...{ [kek]: 0 }} {...{ ["norm" + lol]: 1 }} norm={1} />
const ComplexComputedAttibutesHandling = () => h(Abc, { [kek]: 0, ["norm" + lol]: 1, ["ok"]: 2 })

// Should process children but ignore computed parent
h(`calcualted ${stuff}`, { amazing: "stuff" }, [
  h("h1"),
  h("h2"),
  h("h3"),
  h("div", [ h("div") ])
])

class Comp extends React.Component {
  render() {
    return h("div.example", [
      isStuff && h("h1#heading", { ...getProps, ...getKnobs(), stuff: "" }),
      isStuff
        ? h("h1#heading", { ...getProps, ...getKnobs(), stuff: "" })
        : h("h1#heading", "heading"),
      h("h1#heading", { ...getProps, ...getKnobs(), stuff: "" }),
      h("h1#heading", getChildren),
      h(ANIMATIONS[country], {
        className: "lol"
      }),
      h("h1#heading", getChildren(), [h("div")]),
      h("div", [h("div", "Some content")]),
      h("h1#heading", "This is hyperscript"),
      h("h2", "creating React.js markup"),
      h(
        AnotherComponent,
        { foo: "bar", bar: () => ({}), shouldRender: thing.length > 0 },
        [
          h("li", [h("a", { href: "http://whatever.com" }, "One list item")]),
          h("li", "Another list item")
        ]
      )
    ]);
  }
}
Code After:
import React from 'react'
import h from 'react-hyperscript'

import hx from 'shit'

const StatelessComponent = props => <h1 />

const StatelessWithReturn = props => {
  return <div className="class" />
}

function HyperscriptAsRegularFunction(props) {
  return <h1 />
}

const HyperscriptAsVariable = <div className="lol" someProp="lol" />

const HyperscriptWithExpressionAsChildren = (
  <AnotherComponent foo="bar" bar={() => ({})} shouldRender={thing.length > 0}>
    {arr.map(() => <h1 />)}
  </AnotherComponent>
)

// Should be ignored from transforming
const FirstArgTemplateLiteralWithComputedExpressions = h(`div.lol${stuff}`, {
  someProp: 'lol'
})

// Not computed so should be fine
const FirstArgTemplateLiteral = <div className="lol" someProp="lol" />

// Should be ignored
const WhenFirstArgumentIsFunctionThatIsCalled = () =>
  h(getLoadableAnimation('pageCareersDeliver'), [h(fn())])

const ComputedRootWithObjectPropertyDeclaration = () =>
  h(
    ANIMATIONS[country],
    {
      className: 'lol',
      content: (
        <div className="selectItem">
          <div>{label}</div>
          <div className="flag">
            <RoundFlag mix="flag" size="xs" code={currencyData.countryCode} />
            {// Computed not root should be wrapped in {}
            h(ANIMATIONS[country], { className: 'lol' })}
          </div>
        </div>
      )
    },
    [
      h(ANIMATIONS[country], { className: 'lol' }),
      <h1 />,
      kek && mem,
      surreal ? lol : kek,
      t.tabName,
      lol,
      <div />
    ]
  )

const ThirdArgOnIgnoredIsNotArray = () =>
  h(
    ANIMATIONS[country],
    {
      className: 'lol'
    },
    // This first children in array will be ignored FOR THIS UGLY HACK IN INDEX
    children
  )

h(isCanada ? doStuff : doAnotherStuff, { someProp: true });
<div>{isCanada ? someProps : anotherProps}</div>;
<div {...(isCanada ? someProps : anotherProps)}>SomeChildren</div>;

const SecondArgOnIgnoredIsNotArray = () => h(ANIMATIONS[country], children)

const MultiMemberExpressionWithClosingTag = () => (
  <Pricing.lol.kek className={className}>
    <h1 />
  </Pricing.lol.kek>
)

// to handle h(Abc, { [kek]: 0, ["norm"]: 1 }) to < Abc {...{ [kek]: 0 }} {...{ ["norm" + lol]: 1 }} norm={1} />
const ComplexComputedAttibutesHandling = () => (
  <Abc {...{ [kek]: 0 }} {...{ ['norm' + lol]: 1 }} ok={2} />
)

// Should process children but ignore computed parent
h(`calcualted ${stuff}`, { amazing: 'stuff' }, [
  <h1 />,
  <h2 />,
  <h3 />,
  <div>
    <div />
  </div>
])

class Comp extends React.Component {
  render() {
    return (
      <div className="example">
        {isStuff && <h1 id="heading" {...getProps} {...getKnobs()} stuff="" />}
        {isStuff ? (
          <h1 id="heading" {...getProps} {...getKnobs()} stuff="" />
        ) : (
          <h1 id="heading">heading</h1>
        )}
        <h1 id="heading" {...getProps} {...getKnobs()} stuff="" />
        <h1 id="heading">{getChildren}</h1>
        {h(ANIMATIONS[country], {
          className: 'lol'
        })}
        <h1 id="heading" {...getChildren()}>
          <div />
        </h1>
        <div>
          <div>Some content</div>
        </div>
        <h1 id="heading">This is hyperscript</h1>
        <h2>creating React.js markup</h2>
        <AnotherComponent
          foo="bar"
          bar={() => ({})}
          shouldRender={thing.length > 0}
        >
          <li>
            <a href="http://whatever.com">One list item</a>
          </li>
          <li>Another list item</li>
        </AnotherComponent>
      </div>
    )
  }
}

Usage

Install codemod npm install -g @codemod/cli

Then install in root of your project npm install babel-plugin-hyperscript-to-jsx

Run it like that from node_modules:

codemod --plugin ./node_modules/babel-plugin-hyperscript-to-jsx/src/index.js ./src

Also, you may like to pretty print it immediately using prettier

codemod --plugin ./node_modules/babel-plugin-hyperscript-to-jsx/src/index.js ./src --printer prettier

Remove babel-plugin-hyperscript-to-jsx from package.json

If there is any issues, let me know in the issues tab here at GitHub.

You can run it against exact file too e.g. ./src/index.js

codemod --plugin ./node_modules/babel-plugin-hyperscript-to-jsx/src/index.js ./src/index.js --printer prettier

Limitations

  1. When h is called this way
h("FirstThing", this.getSomePropsOrChildren());

Second argument will be a children (to break everything), cause to get whether second argument expression is returning children or props of object is almost impossible.

  1. All computed first arguments to h like h(STUFF[computed]) or h(.stuff ${anotherClass}) is impossible to codemod, so they will be ignored, and you will need to fix it yourself, they will be kept as is, but their array second and third arguments will be processed with the same approach.

Fix all that by yourself :)

(it's possible but will require further analysis of AST with hardcore traversal and I don't think it worth it)

Integration with WebStorm/VS Code to do it nicely file by file

Preconditions:

npm i -g @codemod/cli babel-plugin-hyperscript-to-jsx

WebStorm:

  1. Go to Preferences -> External Tools -> Click plus to add tool.
  2. Config:
Name: h to JSX
Program: codemod
Arguments: -p <your global node_modules location>/babel-plugin-hyperscript-to-jsx/src/index.js $FilePathRelativeToProjectRoot$
Working directory: $ProjectFileDir$

In advanced settings:
Tick on: Sync file after execution
  1. Open file you want to transform Right Click -> External Tools -> h to JSX -> Apply prettier/code formatting -> Enjoy
  2. For even better experience go to. Preferences -> Keymap -> External Tools -> External Tools -> h to JSX -> Attach some key combination

VS Code:

  1. Open command pallete
  2. >Tasks: Configure Task
  3. Press Up -> Select: Task from tasks.json template (or something like that)
  4. Copy and paste this:
{
    // See https://go.microsoft.com/fwlink/?LinkId=733558
    // for the documentation about the tasks.json format
    "version": "2.0.0",
    "tasks": [
        {
            "label": "H to JSX",
            "type": "shell",
            "command": "codemod -p <your global node_modules location>/babel-plugin-hyperscript-to-jsx/src/index.js ${file}"
        }
    ]
}
  1. Open command pallete and ask it to open keybindings.json
  2. Add this:
    {
        "key": "cmd+e",
        "command": "workbench.action.tasks.runTask",
        "args": "H to JSX"
    }
  1. Open any file and press cmd+e to apply codemod on file.
  2. Or if you don't want to bloat your keybindings.json just open Command pallete and type. Run task -> Enter -> Find in the list "H to JSX" -> Enter (Usually will be on top)
  3. Apply formatting and enjoy

For Revolut plugin to work.

Webstorm:
  • Add to command line arguments -o index={\"revolut\":true} before the $FilePathRelativeToProjectRoot$
VS Code:
  • Add to command line arguments -o index='{\"revolut\":true}' before the ${file}
Note that the project description data, including the texts, logos, images, and/or trademarks, for each open source project belongs to its rightful owner. If you wish to add or remove any projects, please contact us at [email protected].