1.0.0-beta.66 • Published 3 years ago

@expressive/babel-plugin-react v1.0.0-beta.66

Weekly downloads
87
License
MIT
Repository
github
Last release
3 years ago

XJS

If you develop with React, chances are you know JSX, its de-facto language so to speak. Expressive, or XJS for short, is an alternative syntax. It aims to let React developers write their components and apps in a more elegant way. It too generates code used by the react runtime, however it also adds useful features at the language level which can optimize how we make our components.

  • first class styles
  • you don't need closing tags
  • you don't need to {} escape data or props
  • uses actual if and for statements for conditionals and iteration
  • automatically includes runtime imports

XJS is able to outstrip the feature set of JSX by taking what is a factory approach, as-well as relying on a deep build-time process. Instead of simply transforming markup into a tree of createElement calls, it will construct and output a factory which assembles component-objects consumed by react. Among other things, this causes a developer to not need to write much of the logic they'd use to make anything beyond dead simple. Instead it allows you to easily and dryly declare anything from simple to the most complex of elements.

Think of it like this: Where JSX is a markup language, XJS treats your components like a script.

Install

The easiest way to add Expressive to your project is to use one of the plugins. There is one for each of the most common environments.

  • React @expressive/babel-preset-react
  • Native @expressive/babel-preset-react-native

React.js / NEXT.js

Pick version for your environment.

npm install @expressive/babel-preset-react

.babelrc

Add web or next to your babel presets, keep preset-react if you want JSX to still work (recommended) Note that babel infers babel-preset so you should exclude that

{
    "presets": [
    	"@babel/preset-env",
    	"@babel/preset-react",
        "@expressive/react"
    ]
}

@expressive/react in babel-presets is NOT to be confused with package @expressive/react

index.js

@expressive/react is a peer dependancy. In most cases without it, exceptions will be thrown.

import StyledApp from "@expressive/react";

export default () => do { 
  StyledApp() >> App()
}

const App = () => do {
  span, do {
    color: "blue";
    font: "20px";

    "Hello World!"
  }
}

React Native

npm install @expressive/babel-preset-react-native

.babelrc

Must replace react-native with @expressive-react/native You may also remove babel-preset-react-native from dependancies Note that babel infers babel-preset even for @org packages

{
    "presets": [
        "@expressive/react-native"
    ]
}

index.js

import { AppRegistry } from 'react-native';

const App = () => do {
  //view, text are lower-case here given that View, and Text are inferred automatically.

  view >> text `Hello World`;
}

AppRegistry.registerComponent('Expressive', () => App);

How does Expressive stack up against JSX?

Hello World

//named template, shorthand for element with innerText
//optimized automatically if no expressions are present, so use it anywhere

var Hello = () => do {
  span `Hello Expressive`;
}
var Hello = () => (
  <span>Hello World</span>
)

Hello Somebody

//left hand side of `>` is non-parsed simple child of element.
//Anything (syntax-wise) can go there: variables, maths, calls, etc.
//Expects to evaluate to a String or React.Element

var Hello = ({ name }) => do {
  span `Hello`;
  br;
  span > name;
}
var Hello = ({ name }) => (
  <span>Hello</span>
  <br/>
  <span>{name}</span>
)

What about children?

//each `do{}` represents a new context within the element
//it's affixed to, similar to a function body.

var WithKids = () => do {
  Parent, do {
    Child; 
    GrandChild, do {
      AwesomeGrandChild;
    };
  }
}
var WithKids = () => (
  <Parent>
    <Child/>
    <GrandChild>
      <GreatGrandChild/>
    </GrandChild>
  </Parent>
)

Let's see props

//this doesn't actually set any variables
//name = value as an argument works pretty straight forward
//named template, also shorthand for text props (when an argument)

var WithProps = ({ baz }) => do {
  SomeComponent(
    foo = "bar",
    bar = baz,
    baz `foo`
  );
}
var WithProps = ({ baz }) => (
  <SomeComponent 
    foo = "bar" 
    bar = {baz}
    baz = "foo"
  />
)

Nested Elements (elements wrapping only one child)

//right-hand side of `>>` is parsed element-child of left-hand

var DeeplyNested = ({ baz, prop }) => do {
  Parent(
    some `prop`, 
    another = prop
  )
  >> Child(foo `bar`)
  >> GrandChild(bar = baz)
  >> GreatGrandChild 
  >> ExcellentGrandChild `Actually that wasn't so hard.`
}
var DeeplyNested = ({ baz, prop }) => (
  <Parent 
    some = "prop", 
    another = { prop }>
    <Child foo = "bar">
      <GrandChild bar = {baz}>
        <GreatGrandChild>
          <ExcellentGrandChild>When will it end??</ExcellentGrandChild>
        </GreatGrandChild>
      </GrandChild>
    </Child>
  </Parent>
)

Spread Props, Truthy Props, and even Object-style inclusions

// you may also indent, format nested elements as you prefer.

var WithPassThroughProps = ({ foo, ...rest }) => do {
  SomeComponent({ isSpecial, ...rest }) >>
    AnotherComponent(
      { foo }, 
      bar `baz`, 
      baz = 3
    )
}
//isSpecial = "true"

var WithPassThroughProps = ({ foo, ...rest }) => (
  <SomeComponent isSpecial { ...rest } />
    <AnotherComponent 
      foo = {foo} 
      bar = "baz" 
      baz = {3} />
  </SomeComponent>
)

What about children and props?

//props and children can exist in same space
//assignments are props. Calls, strings, and sequences are elements.

var WithBoth = ({ baz, ipsum }) => do {
  SomeComponent, do {
    lorem = ipsum;
    something = "else";

    Child1 `Hello`,
      foo `bar`;
    Child2 `World`,
      bar = baz;
  }
}
var WithBoth = ({ baz, ipsum }) => (
  <SomeComponent
    lorem = { ipsum }
    something = "else">
    <Child1 foo = "bar">Hello</Child1>
    <Child2 bar = {baz}>World</Child2>
  </SomeComponent>
)

Conditional components

//automatically provides false if untrue without alternate clause
//bracketed can insert a fragment with any number of elements

var Conditional = ({ shouldShow, showFirstNotSecond }) => do {
  SomeComponent, do {
  
    some = "thing"

    if(shouldShow)
      InnerComponent `Hey Whatsup`;

    if(showFirstNotSecond)
      TheFirstOne `Hey I'm the first one`;
    else {
      TheSecondOne `I'm actually the second one`;
      BonusElement `And why not bring a friend since it's so easy 💪`;
    }
  }
}
var Conditional = ({ shouldShow, showFirstNotSecond }) => (
  <SomeComponent some = "prop">
    {shouldShow &&  
      (<InnerComponent>Hey Whatsup</InnerComponent>)
    }
    {showFirstNotSecond
      ? (<TheFirstOne>Hey Im the first one</TheFirstOne>) 
      : (<TheSecondOne>Im actually the second one</TheSecondOne>)
    }
  </SomeComponent>
)

Iterated Components from an Array

const names = ["Bob", "Rick", "Mike", "Joe"];
var Loop = () => do {
  SomeComponent, do {
    for(const name of names)
      div `Hello ${name} nice to meet you!`
  }
}
var Loop = () => (
  <SomeComponent>
    {names.map((name) => (
      <div>Hello {name} nice to meet you!</div>
    ))}
  </SomeComponent>
)

But wait, Theres more!

That's it for simple comparisons! Further features can't even be replicated in stateless JSX. Check out next page for more things that expressive can do which JSX outright cannot.

Contributing and Conversation

I made a Slack group if anyone wants to chat. 🙂

1.0.0-beta.66

3 years ago

1.0.0-beta.64

3 years ago

1.0.0-beta.65

3 years ago

1.0.0-beta.62

3 years ago

1.0.0-beta.63

3 years ago

1.0.0-beta.60

3 years ago

1.0.0-beta.61

3 years ago

1.0.0-beta.59

3 years ago

1.0.0-beta.57

3 years ago

1.0.0-beta.58

3 years ago

1.0.0-beta.55

3 years ago

1.0.0-beta.56

3 years ago

1.0.0-beta.53

3 years ago

1.0.0-beta.54

3 years ago

1.0.0-beta.52

3 years ago

1.0.0-beta.51

3 years ago

1.0.0-beta.50

3 years ago

1.0.0-beta.49

3 years ago

1.0.0-beta.48

4 years ago

1.0.0-beta.47

4 years ago

1.0.0-beta.45

4 years ago

1.0.0-beta.46

4 years ago

1.0.0-beta.44

4 years ago

1.0.0-beta.43

4 years ago

1.0.0-beta.42

4 years ago

1.0.0-beta.38

4 years ago

1.0.0-beta.36

4 years ago

1.0.0-beta.35

4 years ago

1.0.0-beta.34

4 years ago

1.0.0-y.0

4 years ago

1.0.0-beta.31

4 years ago

1.0.0-beta.29

4 years ago

1.0.0-beta.30

4 years ago

1.0.0-beta.27

4 years ago

1.0.0-beta.24

5 years ago

1.0.0-beta.23

5 years ago

1.0.0-beta.22

5 years ago

1.0.0-beta.21

5 years ago

1.0.0-beta.20

5 years ago

1.0.0-beta.19

5 years ago

1.0.0-beta.17

5 years ago

1.0.0-beta.16

5 years ago

1.0.0-beta.15

5 years ago

1.0.0-beta.14

5 years ago

1.0.0-beta.13

5 years ago

1.0.0-beta.12

5 years ago

1.0.0-beta.11

5 years ago

1.0.0-beta.10

5 years ago

1.0.0-beta.9

5 years ago

1.0.0-beta.8

5 years ago

1.0.0-beta.7

5 years ago

1.0.0-beta.6

5 years ago

1.0.0-beta.5

5 years ago

1.0.0-beta.4

5 years ago