Skip to content

tomasr8/pyjsx

Repository files navigation

PyJSX - Write JSX directly in Python

PyPI - Version

from pyjsx import jsx, JSX

def Header(style, children) -> JSX:
    return <h1 style={style}>{children}</h1>

def Main(children) -> JSX:
    return <main>{children}</main>

def App() -> JSX:
    return (
        <div>
            <Header style={{"color": "red"}}>Hello, world!</Header>
            <Main>
                <p>This was rendered with PyJSX!</p>
            </Main>
        </div>
    )

Installation

Get it via pip:

pip install python-jsx

Minimal example (using the coding directive)

Tip

There are more examples available in the examples folder.

There are two supported ways to seamlessly integrate JSX into your codebase. One is by registering a custom codec shown here and the other by using a custom import hook shown below.

# hello.py
# coding: jsx
from pyjsx import jsx

def hello():
    print(<h1>Hello, world!</h1>)
# main.py
from pyjsx import auto_setup

from hello import hello

hello()
$ python main.py
<h1>Hello, word!</h1>

Each file containing JSX must contain two things:

  • # coding: jsx directive - This tells Python to let our library parse the file first.
  • from pyjsx import jsx import. PyJSX transpiles JSX into jsx(...) calls so it must be in scope.

To run a file containing JSX, the jsx codec must be registered first which can be done with from pyjsx import auto_setup. This must occur before importing any other file containing JSX.

Minimal example (using an import hook)

Tip

There are more examples available in the examples folder.

# hello.px
from pyjsx import jsx

def hello():
    print(<h1>Hello, world!</h1>)
# main.py
from pyjsx import auto_setup

from hello import hello

hello()
$ python main.py
<h1>Hello, word!</h1>

Each file containing JSX must contain two things:

  • The file extension must be .px
  • from pyjsx import jsx import. PyJSX transpiles JSX into jsx(...) calls so it must be in scope.

To be able to import .px, the import hook must be registered first which can be done with from pyjsx import auto_setup (same as for the codec version). This must occur before importing any other file containing JSX.

Supported grammar

The full JSX grammar is supported. Here are a few examples:

Normal and self-closing tags

x = <div></div>
y = <img />

Props

<a href="example.com">Click me!</a>
<div style={{"color": "red"}}>This is red</div>
<span {...props}>Spread operator</span>

Nested expressions

<div>
    {[<p>Row: {i}</p> for i in range(10)]}
</div>

Fragments

fragment = (
    <>
        <p>1st paragraph</p>
        <p>2nd paragraph</p>
    </>
)

Custom components

A custom component can be any function that takes **kwargs and returns JSX or a plain string. The special prop children is a list containing the element's children.

def Header(children, **rest):
    return <h1>{children}</h1>

header = <Header>Title</Header>
print(header)

Prior art

Inspired by packed and pyxl4.