Skip to main content

Basic Markup eXpressions

Project description

BMX - Basic Markup eXpressions

A DSL for representing HTML/XML in Python using an expression-like syntax. Why? You get to use the Python syntax you already know.

Example

This example from the Jinja2 website can be represented in BMX like so:

mydoc = (
 DOCTYPE.html
 +html(lang='en') 
   +head
     +title +"My Webpage" -title
   -head
   +body
     +ul('#navigation') 
       +(
         +li
           +a(href=item.href) +item.caption -a
         -li
       for item in navigation)
     -ul

     +h1 +"My Webpage" -h1
     +a_variable

     # a comment
   -body
 -html)

Note: Just as with ordinary Python expressions, multi-line BMX expressions must be surrounded by parentheses.

Installation and Dependencies

bmx is tested on CPython versions 3.6-3.9. It has 2 dependencies: singledispatchmethod (backported from 3.8) and MarkupSafe - to escape html in strings.

pip install bmx

Usage

An example using Flask (available in the top-level source directory):

# flask_greeter.py
from bmx.htmltags import (
    html, 
    head, 
    title,
    body,
    p
)
from flask import Flask

app = Flask(__name__)

@app.route('/<name>')
def greeter(name: str):
    return str(
        # fmt: off
        +html
          +head
            +title +"Flask Greeter" -title
          -head
          +body
            +p +f"Hello {name}" -p
          -body
        -html
        # fmt: on
    )

Install Flask then run it as:

FLASK_APP=flask_greeter.py flask run

Go to https://127.0.0.1:5000/<your_name> in your browser (eg. https://127.0.0.1:5000/Stuart) and you will see the message.

Table of Conversions

Type HTML BMX Comment/Mnemonic
Opening tag <div> +div Mnemonic: Adding content
Closing tag </div> -div Mnemonic: opposite of adding content
Self-closing tag <input/> +input Self-closing tag are pre-defined
Attributes <a href="/">Home</a> +a(href="/") +"Home" -a Mnemonic: attributes are keyword arguments.
Attributes <button aria-label="Close">X</button> +button(aria_label="Close") +"X" -button Note: Underscores in keyword arguments are replaced with dashes
Attributes <input type="text"> +input_(type_="text") Note: Append an underscore to avoid conflicts with Python keywords
Attributes: shorthand for id and class <div id="userinput" class="credentials" > +div('#userinput.credentials') #id .classname
Attributes: shorthand for class <div class="col-sm-8 col-md-7 py-4"> +div .col_sm_8 .col_md_7 .py_4 .classname Underscores are replaced with dashes
Composing tags and content <h1>The Title</h1> +h1 +"The Title" -h1 Mnemonic: think string concatenation ie. "Hello " + "World!"

How does it work?

We define a Tag class which overrides the unary +/- and binary +/- operators to model the opening and closing tags of HTML. We provide a __call__ method to model HTML attributes as keyword arguments and a __getattr__ method to provide a shorthand for HTML classes (see above). A Tag is instantiated for every HTML tag and is available with a from bmx.htmltags import html, head, body, span.

MarkupSafe

bmx uses MarkupSafe to escape HTML from strings. If you are sure that you don't want to escape the HTML in a string, you can wrap it in a Markup object and the string will be included as-is.

Autoformatters

Black

To use the Black uncompromising autoformatter, surround your BMX markup with #fmt: off and #fmt: on comments like this:

result = (
    # fmt: off
    +html
        +body
            +h1 +"My Page" -h1
        -body
    -html
    # fmt: on
)

Autopep8

To use autopep8, you can use the #fmt: off and #fmt: on comments as above or turn off 2 fixes:

  • E225 - Fix missing whitespace around operator.
  • E131 - Fix hanging indent for unaligned continuation line.

whereever you put your autopep8 configuration

ignore = E225,E131

Changelog

0.0.3

Fixes for:

  • Class list can only be created once #4
  • Keyword arguments in snake_case should be translated to kebab-case #3
  • README improvements/fixes

0.0.2

  • default to using MarkupSafe for strings
  • include DOCTYPE in htmltags module
  • README improvements/fixes

0.0.1

  • Initial release

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

bmx-0.0.3.tar.gz (16.5 kB view hashes)

Uploaded Source

Built Distribution

bmx-0.0.3-py3-none-any.whl (14.5 kB view hashes)

Uploaded Python 3

Supported by

AWS AWS Cloud computing and Security Sponsor Datadog Datadog Monitoring Fastly Fastly CDN Google Google Download Analytics Microsoft Microsoft PSF Sponsor Pingdom Pingdom Monitoring Sentry Sentry Error logging StatusPage StatusPage Status page