reactpy icon indicating copy to clipboard operation
reactpy copied to clipboard

Syntax similar to JSX

Open Archmonger opened this issue 2 years ago • 13 comments

Current Situation

ReactJS has a method of HTML templating called JSX. We currently do not have an equivalent.

There is a WIP tag string PEP that proposes adding template literals to Python. We will need this to write JSX in Python in the same way it has been used to do so in Javascript.

While the tag string PEP remains in development, an interim transpiler has been proposed that would allow us to use a similar syntax before the PEP is accepted, and in older versions of Python. The syntax would look something like this:

button_style = {"font_style": "bold"}
button_text = "Click me!"
view = html @ f"<button on_click={lambda event: ...} style={button_text}>{button_text}</button>"
reveal_type(view)  # revealed type is: VdomDict

Proposed Actions

Aid in the development of this proposed transpiler and then develop an html tag function. An initial implementation of an html tag can be found here.

Archmonger avatar Feb 09 '23 21:02 Archmonger

If a transpiler is required to get the same sort of syntax as JSX, then how would template literals be any better than fstrings?

bitnom avatar Feb 25 '23 18:02 bitnom

The main purpose of template literals is to have a dedicated syntax. Transpilers allow you to write any syntax you'd like in your Python files, and at least for JSX, that's already been done. The problem, and the reason I suspect Pyxl never saw wide adoption, is because it breaks all the tools you would normally use with a Python file (e.g. black, flake8, pylint, mypy, the list goes on...). You could as I proposed above, co-opt an existing syntax which is seen infrequently (e.g. tag @ f"..."), but without standardization, no one is going to create tooling that understands that bespoke syntax and provides highlighting and auto-completions.

rmorshea avatar Feb 25 '23 20:02 rmorshea

I've published an import-time transpiler that implements that aforementioned tag string spec.

$ pip install tagstr
# tagstr: on
name = "world"
print @ f"hello {name}!"
hello  (<function <lambda> at 0x7f7a8586b920>, 'name', None, None) !

I don't think this is ready for production yet, but with some more work behind this I think it provides a promising alternative to the current, and rather disjointed, patterns for constructing views in ReactPy. Integrating this into ReactPy could also act as a compelling real-world use case for the Tag String PEP itself.

rmorshea avatar Apr 22 '23 23:04 rmorshea

That could be PSX python syntax extension, or PYX python XML

mtrunkbear avatar Jun 13 '23 14:06 mtrunkbear

@rmorshea Very good work bro, i was reading the tag string docs and tutorial and i think that is a very useful aproximation.

mtrunkbear avatar Jun 13 '23 15:06 mtrunkbear

Just for the sake of "state of the art", there is also this project named packed that is similar to pyxl3, but the syntax looks a little bit more like like tsx syntax on some small aspects. I guess the same criticisms apply to this project about the lake of syntax highlight,...

aranega avatar Jul 13 '23 15:07 aranega

I use BeautifulSoup analyse xml, then it can work below.

@component
def DataList(items, functest=None, filter_by_priority=None, sort_by_priority=False):
    if filter_by_priority is not None:
        items = [i for i in items if i["priority"] <= filter_by_priority]
    if sort_by_priority:
        items = sorted(items, key=lambda i: i["priority"])
    list_item_elements = [f"""<li key="{i["id"]}">{i["text"]}</li>""" for i in items]
    test = "<sdfa>"
    return """
        <ul>
            abcdedfe
            {functest()}
            {"".join(list_item_elements)}
            {test}
            {test}
            def
            ""{""}""
            <div>test</div>
        </ul>
    """

@component
def TodoList(text=""):
    def functest():
        return ("test-----------------------abc")
    tasks = [
        {"id": 0, "text": f"{text} Make breakfast3", "priority": 0},
        {"id": 1, "text": f"{text} Feed the dog", "priority": 0},
        {"id": 2, "text": f"{text} Do laundry", "priority": 2},
    ]
    return """
        <section>
            <h1>My Todo List</h1>
            <DataList items={tasks} functest={functest} filter_by_priority={1} sort_by_priority={True} />
        </section>
    """

@component
def Test():
    a = 2
    b = 3
    return """
        <h1 id="1" class_name="abc">My Todo List {a + b} Test PSX</h1>
        <ul id="2">
            <li id="5">"Design {23} a cool new app</li>
            <li id="4">Build"</li>
            <li>"Share it with the world!</li>
        </ul>
        <TodoList class_name="abc" />
        <TodoList text="abcd">
            <div>abc</div>
        </TodoList>
        <img
            src="https://picsum.photos/id/237/500/300"
            class="img-fluid"
            style="width: 50%; margin-left: 25%;"
            alt="Billie Holiday"
            tabindex="0"
        />
    """

zx013 avatar Jan 30 '24 03:01 zx013

There is a project that this issue brought to my mind.

RudreshVeerkhare/ReactPy: React implementation in Python 3, which runs on the client-side.

I have never used this project, but I have examined its examples. It allows creating files with the .pyx extension and in these files, you can write HTML with Python, without doing any string formatting.

And I also want to highlight these resources:

And finally, I love Python syntax and hate micro-syntaxes (Jinja counts).

hasansezertasan avatar Feb 02 '24 21:02 hasansezertasan

There is a project that this issue brought to my mind.

RudreshVeerkhare/ReactPy: React implementation in Python 3, which runs on the client-side.

I have never used this project, but I have examined its examples. It allows creating files with the .pyx extension and in these files, you can write HTML with Python, without doing any string formatting.

And I also want to highlight these resources:

And finally, I love Python syntax and hate micro-syntaxes (Jinja counts).

ReactPy is client side but reactpy is server side. There are two ways to analyze pyx, BeautifulSoup and pypeg2. Then how to use js/ts. component library may be important, reactpy get the easy way get it.

zx013 avatar Feb 03 '24 00:02 zx013

ReactPy is client side but reactpy is server side. There are two ways to analyze pyx, BeautifulSoup and pypeg2. Then how to use js/ts. component library may be important, reactpy get the easy way get it.

Yep, thanks for informing 🤩.

hasansezertasan avatar Feb 03 '24 00:02 hasansezertasan

I just discovered another package that lets you write HTML inside python, check it out: twidi/mixt: Write html components directly in python and you have a beautiful but controversial MIXTure

hasansezertasan avatar Feb 06 '24 04:02 hasansezertasan

I can see there's a pretty heavy want for a JSX style syntax for ReactPy.

Ideally we would have added support for this once Python and code editors (such as VS Code) add support for syntax highlighting on strings. But perhaps we should release support for it for early adopters to test it out.

Archmonger avatar Feb 06 '24 06:02 Archmonger

Any progress related to this

Need a transpiler with .pyx extension

Currently rust has it already implemented in their yew framework https://yew.rs/docs/concepts/html Javascript has jsx already

There will be a need for transpilers so that a python file can import json, css as string Without a transpiler this project this library is very hard to use

(
    <div>
        <div data-key="abc"></div>
        <div class="parent">
            <span class="child" value="anything"></span>
            <label for="first-name">{ "First Name" }</label>
            <input type="text" id="first-name" value="placeholder" />
            <input type="checkbox" checked=true />
            <textarea value="write a story" />
            <select name="status">
                <option selected=true disabled=false value="">{ "Selected" }</option>
                <option selected=false disabled=true value="">{ "Unselected" }</option>
            </select>
        </div>
    </div>
)

With transpiler

import reactpy import render

def hello_world():
    return <h1>Hello world</h1>

render(hello_world, '#root')

Should transpile to

```py
import reactpy import render

def hello_world():
    return h('h1', 'Hello world')

render(hello_world, '#root')

arindampradhan avatar May 18 '24 07:05 arindampradhan