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 details)

Uploaded Source

Built Distribution

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

Uploaded Python 3

File details

Details for the file bmx-0.0.3.tar.gz.

File metadata

  • Download URL: bmx-0.0.3.tar.gz
  • Upload date:
  • Size: 16.5 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: poetry/1.1.2 CPython/3.6.9 Linux/4.19.128-microsoft-standard

File hashes

Hashes for bmx-0.0.3.tar.gz
Algorithm Hash digest
SHA256 179a1a93d5a8da2ec022d0db820a382b950c356173dbb741e422487a1b1203fd
MD5 a8a26bf81654332842fc4a4f43f20519
BLAKE2b-256 8eaacc9cbdd2a2f59fdc046299cef3416cc33b53335ba7fcadac501978dabff8

See more details on using hashes here.

File details

Details for the file bmx-0.0.3-py3-none-any.whl.

File metadata

  • Download URL: bmx-0.0.3-py3-none-any.whl
  • Upload date:
  • Size: 14.5 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: poetry/1.1.2 CPython/3.6.9 Linux/4.19.128-microsoft-standard

File hashes

Hashes for bmx-0.0.3-py3-none-any.whl
Algorithm Hash digest
SHA256 699e7c2b47b3a4f5c2be6f735663c84f37e956c94c8181d3f87193408deb2e32
MD5 6c0a32d18d62f763e8e63f437a64f089
BLAKE2b-256 1653e7ce2adf7dc265329576093673f9a9c49e124ce5a2d36bb7d79b0e24c192

See more details on using hashes here.

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