👩‍💻Type-checked JSX for Rust

Overview

axohtml

Github Actions Rust crates.io License: MPL 2.0

This crate provides the html! macro for building fully type checked HTML documents inside your Rust code using roughly JSX compatible syntax.

This crate is a fork of the great Bodil Stokke's typed-html crate. Opted for a fork instead of maintainership because not currently intending to use or maintain the Wasm compatibility (for now).

Quick Preview

">o_o<"

"The tool company for tool companies"

{ (0..3).map(|_| html!(

">o_o<"

)) }

"Every company should be a developer experience company"

); let doc_str = doc.to_string();">
let mut doc: DOMTree<String> = html!(
    
        
            <span class="pl-s">"Hello Axo"</span>
            Metadata::Author content="Axo Developer Co."/>
        
        
            

">o_o<"

"official"> "The tool company for tool companies"

{ (0..3).map(|_| html!(

"emphasis"> ">o_o<"

)) }

"citation-needed"> "Every company should be a developer experience company"

); let doc_str = doc.to_string();

Syntax

This macro largely follows JSX syntax, but with some differences:

  • Text nodes must be quoted, because there's only so much Rust's tokeniser can handle outside string literals. So, instead of

    Hello

    , you need to write

    "Hello"

    . (The parser will throw an error asking you to do this if you forget.)
  • Element attributes will accept simple Rust expressions, but the parser has its limits, as it's not a full Rust parser. You can use literals, variables, dotted properties, type constructors and single function or method calls. If you use something the parser isn't currently capable of handling, it will complain. You can put braces or parentheses around the expression if the parser doesn't understand it. You can use any Rust code inside a brace or parenthesis block.

Valid HTML5

The macro will only accept valid HTML5 tags, with no tags or attributes marked experimental or obsolete. If it won't accept something you want it to accept, we can discuss it over a pull request (experimental tags and attributes, in particular, are mostly omitted just for brevity, and you're welcome to implement them).

The structure validation is simplistic by necessity, as it defers to the type system: a few elements will have one or more required children, and any element which accepts children will have a restriction on the type of the children, usually a broad group as defined by the HTML spec. Many elements have restrictions on children of children, or require a particular ordering of optional elements, which isn't currently validated.

Attribute Values

Brace blocks in the attribute value position should return the expected type for the attribute. The type checker will complain if you return an unsupported type. You can also use literals or a few simple Rust expressions as attribute values (see the Syntax section above).

The html! macro will add an .into() call to the value expression, so that you can use any type that has an Into trait defined for the actual attribute type A.

As a special case, if you use a string literal, the macro will instead use the FromStr trait to try and parse the string literal into the expected type. This is extremely useful for eg. CSS classes, letting you type class="css-class-1 css-class-2" instead of going to the trouble of constructing a SpacedSet. The big caveat for this: currently, the macro is not able to validate the string at compile time, and the conversion will panic at runtime if the string is invalid.

Example

// parses a string literal
// uses From<[&str, &str, &str]>
// uses a variable in scope
)">
let classList: SpacedSet<Class> = ["foo", "bar", "baz"].into();
html!(
    
"foo bar baz" /> // parses a string literal
["foo", "bar", "baz"] /> // uses From<[&str, &str, &str]>
// uses a variable in scope
{ // evaluates a code block SpacedSet::from(["foo", "bar", "baz"]) } />
)

Generated Nodes

Brace blocks in the child node position are expected to return an IntoIterator of DOMTrees. You can return single elements or text nodes, as they both implement IntoIterator for themselves. The macro will consume this iterator at runtime and insert the generated nodes as children in the expected position.

Example

)) } )">
html!(
    
    { (1..=5).map(|i| html!(
  • { text!("{}", i) }
  • )) }
)

Rendering

You have two options for actually producing something useful from the DOM tree that comes out of the macro.

Render to a string

The DOM tree data structure implements Display, so you can call to_string() on it to render it to a String. If you plan to do this, the type of the tree should be DOMTree to ensure you're not using any event handlers that can't be printed.

); let doc_str = doc.to_string(); assert_eq!("

Hello Axo

", doc_str);">
let doc: DOMTree<String> = html!(
    

"Hello Axo"

); let doc_str = doc.to_string(); assert_eq!("

Hello Axo

"
, doc_str);

Render to a virtual DOM

The DOM tree structure also implements a method called vnode(), which renders the tree to a tree of Nodes, which is a mirror of the generated tree with every attribute value rendered into Strings. You can walk this virtual DOM tree and pass it on to your favourite virtual DOM system.

License

This software is subject to the terms of the Mozilla Public License, v. 2.0. If a copy of the MPL was not distributed with this file, You can obtain one at http://mozilla.org/MPL/2.0/.

Copyright 2018 Bodil Stokke, 2022 Axo Developer Co.

Comments
  • Fix clippy warnings on tests

    Fix clippy warnings on tests

    introduced in axodotdev/axohtml-fork#1 - clippy tests fail due to some annoying to fix warnings in tests. should fix or add config for clippy to skip.

    opened by ashleygwilliams 1
  • allow unsafe text in script

    allow unsafe text in script

    Related to https://github.com/axodotdev/oranda/pull/38, in that PR I have to create a script tag with code in it and right now only the text macro is allowed inside but it should be both since we want to allow people to write scripts as its valid HTML

    opened by SaraVieira 0
  • Fix data attributes && add ability to have script in HTML

    Fix data attributes && add ability to have script in HTML

    This PR does two things

    • Fixes issue where if a data attribute has more than one - it would only make the first one into an hyphen
    • Adds ability to add script tags in HTML so I can add the tracking code at the very bottom
    opened by SaraVieira 0
  • Add support for aria properties in all elements

    Add support for aria properties in all elements

    When trying to add an aria property we get an error

    CleanShot 2022-12-19 at 15 44 35@2x

    There is a todo in the code of where they should be added

    https://github.com/axodotdev/axohtml/blob/main/macros/src/config.rs#L36

    opened by SaraVieira 0
  • allow http_equiv attribute in meta tags

    allow http_equiv attribute in meta tags

    looks like #23 was incomplete, we should add this and do a patch version, 0.4.1

    ---- site::it_builds_the_site stdout ----
    ERROR: <meta http_equiv="Permissions-Policy"> failed to parse attribute value: Matching variant not found
    ERROR: rebuild with nightly to print source location
    thread 'site::it_builds_the_site' panicked at 'failed to parse string literal', src/site/head.rs:59:9
    
    bug 
    opened by ashleygwilliams 0
  • Type meta charset

    Type meta charset

    Right now it accepts any string, but the correct thing would be to only accept valid charsets

    Valid charsets can be found here https://www.iana.org/assignments/character-sets/character-sets.xhtml

    good first issue 
    opened by SaraVieira 0
  • Remove unused functions

    Remove unused functions

    These functions were only used in the old version of the library and are not used anymore, functions are:

    • https://github.com/axodotdev/axohtml/blob/main/macros/src/html.rs#L290
    • https://github.com/axodotdev/axohtml/blob/main/macros/src/lib.rs#L59
    opened by SaraVieira 0
  • Events? Events!

    Events? Events!

    Currently, this package does not appear to handle events. Right now that doesn't matter — generated Oranda pages do not need fancy event listeners. What will we do when we want things, like interactive widgets?

    It seems doing a straight inline event registration on the HTML attribute is not great. (See: https://developer.mozilla.org/en-US/docs/Learn/JavaScript/Building_blocks/Events#inline_event_handlers_%E2%80%94_dont_use_these)

    Will we choose to feed vnode trees into the vDOM library of our choice? Find a way to register and dispatch events ourselves (https://the-guild.dev/blog/react-dom-event-handling-system)? Confine most interactive bits to the Axo dashboard (Sunfish) and add a little bit of script for the rest? Is this a case for Web Components?! We don't know, but we should think about it!

    opened by sarahghp 0
  • start svg implementation

    start svg implementation

    • [ ] <a>
    • [ ] <animate>
    • [ ] <animateMotion>
    • [ ] <animateTransform>
    • [x] <circle>
    • [x] <clipPath>
    • [x] <defs>
    • [x] <desc>
    • [x] <ellipse>
    • [x] <feBlend>
    • [ ] <feColorMatrix>
    • [ ] <feComponentTransfer>
    • [ ] <feComposite>
    • [ ] <feConvolveMatrix>
    • [ ] <feDiffuseLighting>
    • [ ] <feDisplacementMap>
    • [ ] <feDistantLight>
    • [ ] <feDropShadow>
    • [ ] <feFlood>
    • [ ] <feFuncA>
    • [ ] <feFuncB>
    • [ ] <feFuncG>
    • [ ] <feFuncR>
    • [ ] <feGaussianBlur>
    • [ ] <feImage>
    • [ ] <feMerge>
    • [ ] <feMergeNode>
    • [ ] <feMorphology>
    • [ ] <feOffset>
    • [ ] <fePointLight>
    • [ ] <feSpecularLighting>
    • [ ] <feSpotLight>
    • [ ] <feTile>
    • [ ] <feTurbulence>
    • [x] <filter>
    • [ ] <foreignObject>
    • [ ] <g>
    • [ ] <image>
    • [ ] <line>
    • [ ] <linearGradient>
    • [ ] <marker>
    • [ ] <mask>
    • [ ] <metadata>
    • [ ] <mpath>
    • [x] <path>
    • [ ] <pattern>
    • [ ] <polygon>
    • [ ] <polyline>
    • [ ] <radialGradient>
    • [ ] <rect>
    • [ ] \x3Cscript>
    • [ ] <set>
    • [ ] <stop>
    • [ ] <style>
    • [x] <svg>
    • [ ] <switch>
    • [ ] <symbol>
    • [ ] <text>
    • [ ] <textPath>
    • [ ] <title>
    • [ ] <tspan>
    • [ ] <use>
    • [ ] <view>
    status: work in progress 
    opened by SaraVieira 0
  • Add support for SVG

    Add support for SVG

    Right now SVG's are not supported and as it's a common tag we should definitly add support

    This will include adds support for all mentioned elements here: https://developer.mozilla.org/en-US/docs/Web/SVG/Element

    status: PR attached feature: new element 
    opened by SaraVieira 0
Releases(v0.4.1)
  • v0.4.1(Jan 25, 2023)

    🛠️ Fixes

    • ✨ Fix capitalization for Permissions-Policy meta tag- [ashleygwilliams], [pr26]

      This PR updates the capitalization of the Permissions Policy header from Permissions-policy to Permissions-Policy.

    Source code(tar.gz)
    Source code(zip)
  • v0.4.0(Jan 24, 2023)

  • v0.3.0(Jan 2, 2023)

    🎁 Features

    • ✨ Add twitter SEO tag support - SaraVieira, PR17

      Add support for meta tags used for twitter cards as showed in their docs

    🛠️ Fixes

    • ✨ Data Attributes now work with more than one hyphen - SaraVieira, PR10

      Our support for data attributes was limited in the way that it only supported one hyphen in said attributes, well, no more, use as many hyphens as your heart pleases

    • ✨ Allow script tags in HTML - SaraVieira, PR10

      We now allow you to add script tags in the HTML after the body as the HTML standards also allow

    • ✨ Allow unescaped text inscript- SaraVieira, PR14

      Until now we were escaping the text passed down to the script tag and in the script tag is the only place we are sure we don't want to escape that so that's fixed and you can add script tags with unescaped text inside

    Source code(tar.gz)
    Source code(zip)
  • v0.2.0(Dec 19, 2022)

    🎁 Features

    • ✨ New Attribute - aria - SaraVieira

      aria attributes are critical to making the web more accessible to everyone, but most importantly, people with disabilities. These were a to-do item from the original project, and so we to-did them. At least most of them. There are a few open issues if you'd like to help us complete the implementation.

    • ✨ New Attribute - meta:property - SaraVieira

      If you ask the internet why meta tags have a property attribute that isn't in the spec, you won't get great answers. Although not formally specified in HTML5, property attributes in meta tags are important for SEO and the Open Graph Protocol. They are documented in RDFa which is a formal W3C recommendation.

      It is outside the scope of this project to standardize standards bodies. We needed to support the property attribute, and so we did.

    Source code(tar.gz)
    Source code(zip)
  • v0.1.0(Dec 19, 2022)

Owner
axo
axo
Transform jsx/tsx files to reactive views in js/ts to use in Web Components, insert into DOM or integrate with other libraries/frameworks

viewmill Features | Installation | Getting Started | Notes | Examples viewmill is aimed to create complex UIs from a simple form of JSX. It statically

apleshkov 6 Sep 4, 2023
A crate that allows you to mostly-safely cast one type into another type.

A crate that allows you to mostly-safely cast one type into another type. This is mostly useful for generic functions, e.g. pub fn foo<S>(s: S) {

Bincode 3 Sep 23, 2023
Next-generation, type-safe CLI parser for Rust

Next-generation, type-safe CLI parser for Rust

0918nobita 19 Jul 20, 2022
Dynamic, Type-Erased Key-Value Maps in Rust

Dynamic Objects in Rust Do you love Rust but are tired of being constrained by static typing when you need a map to hold values of different types? Do

Travis A. Wagner 12 Feb 25, 2024
Shiva library: Implementation in Rust of a parser and generator for documents of any type

Shiva Shiva library: Implementation in Rust of a parser and generator for documents of any type Features Common Document Model (CDM) for all document

Igumnoff Software 149 Jul 25, 2024
Rustato: A powerful, thread-safe global state management library for Rust applications, offering type-safe, reactive state handling with an easy-to-use macro-based API.

Rustato State Manager A generical thread-safe global state manager for Rust Introduction • Features • Installation • Usage • Advanced Usage • Api Refe

BiteCraft 8 Sep 16, 2024
A new type of shell

A new type of shell

Nushell Project 22.5k Jan 8, 2023
Turbine is a toy CLI app for converting Rails schema declarations into equivalent type declarations in other languages.

Turbine Turbine is a toy CLI app for converting Rails schema declarations into equivalent type declarations in other languages. It’s described as a to

Justin 2 Jan 21, 2022
Web-based tool that allows browsing and comparing symbol and type information of Microsoft Windows binaries across different versions of the OS.

WinDiff About WinDiff is an open-source web-based tool that allows browsing and comparing symbol and type information of Microsoft Windows binaries ac

Erwan Grelet 208 Jun 15, 2023
Like HashSet but retaining INSERTION order and without `Hash` requirement on the Element type.

identified_vec A collection of unique identifiable elements which retains insertion order, inspired by Pointfree's Swift Identified Collections. Simil

Alexander Cyon 4 Dec 11, 2023
Keybinder to type diacrytical characters without needing to hack the layout itself. Supports bindings to the left Alt + letter

Ďíáǩříťíǩád I just thought that it's a shame the word diakritika does not have any diacritics in it. Key points diakritika is a simple Windows daemon

null 4 Feb 26, 2024
A procedural macro that copy-pastes match arms for new type variant enums.

All the same! If you ever had code that looks like this: use std::io; use std::pin::Pin; use std::task::{Context, Poll}; use tokio::io::AsyncWrite; us

Ivan Nikulin 15 Feb 20, 2024
Ergonomic and precise error handling provided by error sets. Inspired by Zig's error set type.

Error Set Error Set simplifies error management by providing a streamlined method for defining errors and easily converting between them. Resultingly,

Henry 61 Jul 24, 2024
ergonomic and precise error handling built atop type-level set arithmetic

terrors - the Rust error handling library Handling errors means taking a set of possible error types, removing the ones that are locally addressible,

Komora 190 Jul 27, 2024
Rust-advent - Learning Rust by solving advent of code challenges (Streaming live on Twitch every Monday)

Rust advent ?? ?? Learning Rust by implementing solutions for Advent of Code problems. ?? HEY, we are live-streaming our attempts to solve the exercis

Luciano Mammino 20 Nov 11, 2022
Rust-clippy - A bunch of lints to catch common mistakes and improve your Rust code

Clippy A collection of lints to catch common mistakes and improve your Rust code. There are over 450 lints included in this crate! Lints are divided i

The Rust Programming Language 8.7k Dec 31, 2022
Rust-battery - Rust crate providing cross-platform information about the notebook batteries.

battery Rust crate providing cross-platform information about the notebook batteries. Table of contents Overview Supported platforms Install Examples

svartalf 326 Dec 21, 2022
A Rust-based shell script to create a folder structure to use for a single class every semester. Mostly an excuse to use Rust.

A Rust Course Folder Shell Script PROJECT IN PROGRESS (Spring 2022) When completed, script will create a folder structure of the following schema: [ro

Sebastián Romero Cruz 1 Apr 10, 2022
Rust Imaging Library's Python binding: A performant and high-level image processing library for Python written in Rust

ril-py Rust Imaging Library for Python: Python bindings for ril, a performant and high-level image processing library written in Rust. What's this? Th

Cryptex 13 Dec 6, 2022