GithubHelp home page GithubHelp logo

rsx's Introduction

Under heavy research and development, please don't use this yet!

rsx

License: MPL 2.0 Build Status

A compiler plugin for using RSX (JSX-like syntax) as advanced templating and metaprogramming in Rust.

Made possible by the Self Tokenize library, a trait derive for transferring data structures outside of procedural macros from compile-time to run-time.

Take a look at the RSX DOM and RSX Stylesheet crates for the underlying types and implementations, or the RSX parser and Servo CSS parser parsing backends for the parser combinators. To convert these data structures into lower level rendering primitives, see RSX Layout and RSX Primitives, which integrate with Facebook's YOGA library and Servo's Graphics component for building a Servo WebRender-powered gfx::display_list::DisplayList. Finally, rendering to pixels is done via the RSX Renderers crate.

For quick and easy example demos, simply check out here.

Purpose

Documentation

This compiler plugin allows you to freely intertwine JSX-like syntax anywhere into your Rust code.

RSX implements all of the JSX grammar. The purpose and benefits of JSX and RSX are equivalent.

How to use

To get access to the rsx!, css! macros, add this to your Cargo.toml file:

[dependencies]
rsx = { git = "https://github.com/victorporof/rsx.git" }
rsx-primitives = { git = "https://github.com/victorporof/rsx-primitives.git" }

Then, simply import the library into your code and use the rsx!, css! macros to parse RSX and CSS into rsx_dom::DOMNode, or rsx_dom::Stylesheet data structures respectively.

For example:

#![feature(proc_macro)]

extern crate rsx;
extern crate rsx_primitives;

use rsx::{rsx, css};
use rsx_primitives::rsx_stylesheet::types::*;
use rsx_primitives::rsx_dom::types::*;

let stylesheet: Stylesheet = css! { .foo { padding: 1px; } };
let node: DOMNode = rsx! { <div>Hello world!</div> };

Here's some code rendering the first example from Facebook's YOGA library:

let stylesheet: Stylesheet = css! {
  .root {
    width: 500px;
    height: 120px;
    flex-direction: row;
    padding: 20px;
  }
  .image {
    width: 80px;
    margin-right: 20px;
  }
  .text {
    height: 25px;
    align-self: center;
    flex-grow: 1;
  }
};

let node: DOMNode = rsx! {
  <view style={stylesheet.take(".root")}>
    <image style={stylesheet.take(".image")} src="..." />
    <text style={stylesheet.take(".text")}>
      Hello world!
    </text>
  </view>
};

Composability

  • Mixing Rust and RSX is possible
  • Stylesheets can be included as separate CSS files.
  • Composing components is achieved through simple function calls (for now).

example.css

.root {
  width: 500px;
  height: 120px;
  flex-direction: row;
  padding: 20px;
}
.image {
  width: 80px;
  margin-right: 20px;
}
.text {
  height: 25px;
  align-self: center;
  flex-grow: 1;
}

example.rs

fn greeting_str(name: &str) -> String {
  format!("Hello {}!", name)
}

fn render_greeting(name: &str) -> DOMNode {
  let stylesheet = css!("example.css");

  rsx! {
    <text style={stylesheet.take(".text")}>
      { greeting_str(name) }
    </text>
  }
}

fn render_children(name: Option<&str>, image: DOMNode) -> DOMNode {
  rsx! {
    <view>
      { image }
      {
        match name {
          Some(ref n) => render_greeting(n),
          None => <text>No greetings!</text>
        }
      }
    </view>
  }
}

fn render_root() -> DOMNode {
  let stylesheet = css!("example.css");

  rsx! {
    <view style={stylesheet.take(".root")}>
      {
        let name = Some("world");
        let image = <image style={stylesheet.take(".image")} src="..." />;
        render_children(name, image)
      }
    </view>
  }
}

let node = render_root();

The css! macro returns a rsx_dom::Stylesheet instance (coming from the RSX Stylesheet library re-exported through the RSX DOM library), because parsing CSS happens at compile-time.

let styles: rsx_stylesheet::Stylesheet = css! { ... }

The rsx! macro returns a rsx_dom::DOMNode instance (coming from the RSX DOM library). The convertion is automatic between rsx_parser::RSXElement abstract syntax trees to the more convenient rsx_dom::DOMNode elements, because the AST is directly tokenized into a DOM tree to avoid any runtime work! Templating is thus a zero cost abstraction.

let node: rsx_dom::DOMNode = rsx! { ... }

rsx's People

Contributors

victorporof avatar

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.