All Projects → madvas → Jsx To Clojurescript

madvas / Jsx To Clojurescript

Command and library to convert JSX snippets to Om/Reagent/Rum or other Clojurescript-style format.

Programming Languages

clojure
4091 projects
clojurescript
191 projects

Labels

Projects that are alternatives of or similar to Jsx To Clojurescript

Web Mode
web template editing mode for emacs
Stars: ✭ 1,470 (+965.22%)
Mutual labels:  jsx
Operator Mono Atom
Free Operator Mono clone for Atom
Stars: ✭ 120 (-13.04%)
Mutual labels:  jsx
Ink Link
Link component for Ink
Stars: ✭ 133 (-3.62%)
Mutual labels:  jsx
Reactinterface
This is the repository for my course, Building a Web Interface with React.js on LinkedIn Learning and Lynda.com.
Stars: ✭ 113 (-18.12%)
Mutual labels:  jsx
React Native Tutorials
Repo for React Native tutorials from the Cheetah Coding YouTube Channel
Stars: ✭ 118 (-14.49%)
Mutual labels:  jsx
Jstoxml
JavaScript object to XML converter (useful for RSS, podcasts, GPX, AMP, etc)
Stars: ✭ 127 (-7.97%)
Mutual labels:  jsx
Jsxui
Primitive elements to build isomorphic user interfaces in React.
Stars: ✭ 105 (-23.91%)
Mutual labels:  jsx
Dependency Cruiser
Validate and visualize dependencies. Your rules. JavaScript, TypeScript, CoffeeScript. ES6, CommonJS, AMD.
Stars: ✭ 2,326 (+1585.51%)
Mutual labels:  jsx
React Structured Data
React Structured Data provides an easy way to add structured data to your React apps
Stars: ✭ 120 (-13.04%)
Mutual labels:  jsx
Storybook Addon Playroom
Design with Playroom inside Storybook, using each story source as a starting point
Stars: ✭ 133 (-3.62%)
Mutual labels:  jsx
React Workshop
⚒ 🚧 This is a workshop for learning how to build React Applications
Stars: ✭ 114 (-17.39%)
Mutual labels:  jsx
Jsx Dom
Use JSX to create DOM elements.
Stars: ✭ 117 (-15.22%)
Mutual labels:  jsx
Preact And Typescript
Some simple patterns for Typescript usage with Preact
Stars: ✭ 127 (-7.97%)
Mutual labels:  jsx
Omi Electron
🚀Build cross platform desktop apps with Omi.js and Electron.js 基于Omi.js和Electron.js构建跨平台的桌面应用
Stars: ✭ 110 (-20.29%)
Mutual labels:  jsx
Mdx
Markdown for the component era
Stars: ✭ 11,948 (+8557.97%)
Mutual labels:  jsx
Prettier
Prettier is an opinionated code formatter.
Stars: ✭ 41,411 (+29907.97%)
Mutual labels:  jsx
Ink Gradient
Gradient color component for Ink
Stars: ✭ 123 (-10.87%)
Mutual labels:  jsx
Redux React Starter
DEPRECATED use the new https://github.com/didierfranc/react-webpack-4
Stars: ✭ 137 (-0.72%)
Mutual labels:  jsx
Preact Minimal
🚀 Minimal preact structure
Stars: ✭ 136 (-1.45%)
Mutual labels:  jsx
Hyperapp One
Hyperapp One is a Parcel boilerplate for quickstarting a web application with Hyperapp (V1), JSX, and Prettier.
Stars: ✭ 129 (-6.52%)
Mutual labels:  jsx

JSX to Clojurescript     jsx   arrow   clojurescript

Moving old ReactJS codebase to Clojurescript? Tired of manually typing ReactJS examples as Clojurescript?

Search no more!

This is command utility and library to convert JSX snippets to Om/Reagent/Rum Clojurescript-style format. Note, this is by no means to be perfect JS->Cljs compiler, output will often still need touch of your loving hand, but, hey, most of dirty work will be done 😎

This library uses acorn-jsx to parse JSX into nice AST. So big kudos there. Since it's Node.js library, you can use this library only in Clojurescript targeted to Node.js

Installation

As command:

npm install -g jsx-to-clojurescript

As library:

[jsx-to-clojurescript "0.1.9"]

As Alfred workflow (Mac only):

I also made workflow, you can download it here Following things are needed:

  • You installed via npm install -g jsx-to-clojurescript
  • Workflow assumes following paths /usr/local/bin/node /usr/local/bin/jsx-to-clojurescript. If you have different, you can change it in Alfred preferences when you open this workflow's run script.

Use it with keyword jsxcljs and paste JSX. To change command line arguments for all following queries use jsxcljs set and type arguments. Don't put arguments into jsxcljs, only JSX string.

Build your own:

lein cljsbuild once

Usage

jsx-to-clojurescript -h

  Usage: jsx-to-clojurescript [options] <string>

  Converts JSX string into selected Clojurescript React library format

  Options:

    -h, --help            output usage information
    -V, --version         output the version number
    -t --target [target]  Target library (om/reagent/rum). Default om
    --ns [string]         Namespace for compoments. Default ui
    --dom-ns [ns]         Namespace for DOM compoments. Default dom
    --lib-ns [ns]         Target library ns. Default for Om: 'om'. Default for reagent & rum: 'r'
    --kebab-tags          Convert tags to kebab-case?
    --kebab-attrs         Convert attributes to kebab-case?
    --camel-styles        Keep style keys as camelCase
    --remove-attr-vals    Remove attribute values?
    --omit-empty-attrs    Omit empty attributes?
    --styles-as-vector    Keep multiple styles as vector instead of merge


Okay let's start with something simple

<div>
    <RaisedButton label="Secondary" secondary={true} style={style} />
    <RaisedButton label="Disabled" disabled={true} style={style} />
</div>
jsx-to-clojurescript --kebab-tags "$(pbpaste)"
(dom/div
 {}
 (ui/raised-button {:label "Secondary", :secondary true, :style style})
 (ui/raised-button {:label "Disabled", :disabled true, :style style}))

Now something more nested... 😉

<AppBar
    title="Title"
    iconElementLeft={<IconButton><NavigationClose /></IconButton>}
    iconElementRight={
      <IconMenu
        iconButtonElement={
          <IconButton><MoreVertIcon /></IconButton>
        }
        targetOrigin={{horizontal: 'right', vertical: 'top'}}
        anchorOrigin={{horizontal: 'right', vertical: 'top'}}
      >
        <MenuItem primaryText="Refresh" />
        <MenuItem primaryText="Help" />
        <MenuItem primaryText="Sign out" />
      </IconMenu>
    }
  />
 jsx-to-clojurescript --kebab-tags --kebab-attrs --ns "u" --target reagent --omit-empty-attrs "$(pbpaste)"
[u/app-bar
 {:title "Title",
  :icon-element-left [u/icon-button [u/navigation-close]],
  :icon-element-right
  [u/icon-menu
   {:icon-button-element [u/icon-button [u/more-vert-icon]],
    :target-origin {:horizontal "right", :vertical "top"},
    :anchor-origin {:horizontal "right", :vertical "top"}}
   [u/menu-item {:primary-text "Refresh"}]
   [u/menu-item {:primary-text "Help"}]
   [u/menu-item {:primary-text "Sign out"}]]}]

Conditions and anonymous functions are okay too! 😃

<div style={{width: '100%', maxWidth: 700, margin: 'auto'}}>
        <Stepper activeStep={stepIndex}>
          <Step>
            <StepLabel>Select campaign settings</StepLabel>
          </Step>
          <Step>
            <StepLabel>Create an ad group</StepLabel>
          </Step>
          <Step>
            <StepLabel>Create an ad</StepLabel>
          </Step>
        </Stepper>
        <div style={contentStyle}>
          {finished ? (
            <p>
              <a href="#"
                onClick={(event) => {
                  event.preventDefault();
                  this.setState({stepIndex: 0, finished: false});
                }}
              >
                Click here
              </a> to reset the example.
            </p>
          ) : (
            <div>
              <p>{this.getStepContent(stepIndex)}</p>
              <div style={{marginTop: 12}}>
                <FlatButton
                  label="Back"
                  disabled={stepIndex === 0}
                  onTouchTap={this.handlePrev}
                  style={{marginRight: 12}}
                />
                <RaisedButton
                  label={stepIndex === 2 ? 'Finish' : 'Next'}
                  primary={true}
                  onTouchTap={this.handleNext}
                />
              </div>
            </div>
          )}
        </div>
      </div>
jsx-to-clojurescript --kebab-tags --kebab-attrs --ns "u" --target reagent --omit-empty-attrs "$(pbpaste)"
[:div
 {:style {:width "100%", :max-width 700, :margin "auto"}}
 [u/stepper
  {:active-step step-index}
  [u/step [u/step-label "Select campaign settings"]]
  [u/step [u/step-label "Create an ad group"]]
  [u/step [u/step-label "Create an ad"]]]
 [:div
  {:style content-style}
  (if finished
    [:p
     [:a
      {:href "#",
       :on-click
             (fn [event]
               (prevent-default event)
               (r/set-state this {:step-index 0, :finished false}))}
      "Click here"]
     " to reset the example."]
    [:div
     [:p (get-step-content step-index)]
     [:div
      {:style {:margin-top 12}}
      [u/flat-button
       {:label        "Back",
        :disabled     (= step-index 0),
        :on-touch-tap handle-prev,
        :style        {:margin-right 12}}]
      [u/raised-button
       {:label        (if (= step-index 2) "Finish" "Next"),
        :primary      true,
        :on-touch-tap handle-next}]]])]]

Mapping? No problem! Notice how map doesn't require any more editing ☺️

<ul>
    {this.props.results.map(function(result) {
        return <ListItemWrapper data={result}/>;
    })}
</ul>
jsx-to-clojurescript --ns "" --target om "$(pbpaste)"
(dom/ul
 {}
 (map
    (fn [result]
        (ListItemWrapper {:data result}))
    (:results props)))

Still not impressed? We can do spread attributes too! 😀

<Animated.View
   {...this.state.panResponder.panHandlers}
   style={this.state.pan.getLayout()}>
   {this.props.children}
 </Animated.View>
jsx-to-clojurescript --ns "" --target om "$(pbpaste)"
(AnimatedView
 (merge
  (:pan-handlers (:pan-responder state))
  {:style (get-layout (:pan state))})
 (:children props))

Array of styles as a nice merge 😌

<View style={styles.container}>
   <View style={[styles.box, {width: this.state.w, height: this.state.h}]} />
</View>
jsx-to-clojurescript --target reagent "$(pbpaste)"
[ui/View
 {:style (:container styles)}
 [ui/View
  {:style
   (merge (:box styles) {:width (:w state), :height (:h state)})}]]

Reagent can do neat trick with ids and classes 😗

<div id="my-id" className="some-class some-other">
    <span className={styles.span}>
        <b className={"home"}>Home</b>
    </span>
</div>
jsx-to-clojurescript --kebab-attrs --target reagent "$(pbpaste)"
[:div#my-id.some-class.some-other
 {}
 [:span {:class-name (:span styles)} [:b.home {} "Home"]]]

LOL variable declarations and conditions?! 😂

< Navigator initialRoute = {
    {
      name: 'My First Scene',
      index: 0
    }
  }
  renderScene = {
    (route, navigator) =>
    < MySceneComponent
    name = {
      route.name
    }
    onForward = {
      () => {
        var nextIndex = route.index + 1,
          myOtherIndex = nextIndex + 10;

        navigator.push({
          name: 'Scene ' + nextIndex,
          index: nextIndex,
        });

        var yetAnotherIndex = myOtherIndex - 1;
      }
    }
    onBack = {
      () => {
        if (route.index > 0) {
          navigator.pop();
        } else if (route.index == 0) {
          someFuction();
          namingIsHardFun();
        } else {
        	var myGreatParam = 5;
          someOtherFunction(myGreatParam);
        }
      }
    }
    />
  }
  />
jsx-to-clojurescript --kebab-attrs --kebab-tags "$(pbpaste)"
(ui/navigator
  {:initial-route {:name "My First Scene", :index 0},
   :render-scene  (fn [route navigator]
                    (ui/my-scene-component
                      {:name (:name route),
                       :on-forward
                             (fn []
                               (let [next-index (+ (:index route) 1)
                                     my-other-index (+ next-index 10)
                                     yet-another-index (- my-other-index 1)]
                                 (push navigator {:name (+ "Scene " next-index), :index next-index}))),
                       :on-back
                             (fn []
                               (if (> (:index route) 0)
                                 (pop navigator)
                                 (if (= (:index route) 0)
                                   (do
                                     (some-fuction)
                                     (naming-is-hard-fun))
                                   (let [my-great-param 5]
                                     (some-other-function my-great-param)))))}))})

No problem with regular JS 😉

const myConst = {some: 34};

function explode(size) {
	var earth = "planet";
	var foo = "bar";
	return boom(earth) * size + myConst;
}

explode(42);

jsx-to-clojurescript "$(pbpaste)"
(do
  (def my-const {:some 34})
  (defn explode [size]
    (let [earth "planet"
          foo "bar"]
      (+ (* (boom earth) size) my-const)))
  (explode 42))

Alright folks, that's enough of examples, I guess you get the picture 😉. If you saw error like ERROR: Don't know how to handle node type <something> it means I haven't implmented some JS syntax yet. Open issue or PR :)

Library API

I won't write API here for 2 reasons:

  1. Not sure if this has many use cases as a library

  2. Core codebase is just ~200 very straightforward lines of code. You will get it very quickly, when you see it. (gotta love Clojure 💜)

If interested, library is extendable, you can easily add other targets other than Om/Reagent (with a single function!)

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].