Skip to main content

Python Hypertext Markup Language - Extension of HTML

Project description

version License tired-fox - phml stars - phml forks - phml

Python Hypertext Markup Language (phml)

Deploy Docs GitHub release issues - phml quality testing test coverage

TOC

view - Documentation

Overview

The idea behind the creation of Python in Hypertext Markup Language (phml), is to allow for web page generation with direct access to python. This language pulls directly from frameworks like VueJS. There is conditional rendering, components, python elements, inline/embedded python blocks, and much more. Now let's dive into more about this language.

Let's start with the new python element. Python is a whitespace language. As such phml has the challenge of maintaining the indentation in an appropriate way. With phml, I have made the decision to allow you to have as much leading whitespace as you want as long as the indentation is consistent. This means that indentation is based on the first lines offset. Take this phml example:

<python>
    if True:
        print("Hello World")
</python>

This phml python block will adjust the offset so that the python is executed as seen below:

if True:
    print("Hello World")

So now we can write python code, now what? You can define functions and variables how you normally would and they are now available to the scope of the entire file. Take, for instance, the example from above, the one with py-src="urls('youtube')". You can define the URL function in the python element and it can be accessed in an element. So the code would look like this:

<python>
def URL(link: str) -> str:
    links = {
        "youtube": "https://youtube.com"
    }
    if link in links:
        return links[link]
    else:
        return ""
</python>

...

<a href="{URL('youtube')}">Youtube</a>

or 

<a :href="URL('youtube')">Youtube</a>

phml combines all python elements and treats them as a python file. All local variables and imports are parsed and stored so that they may be accessed later. With that in mind that means you have the full power of the python programming language.

Next up is inline python blocks. These are represented with {}. Any text in-between the brackets will be processed as python. This is mostly useful when you want to inject a value from python. Assume that there is a variable defined in the python element called message and it contains Hello World!. Now this variable can be used like this, <p>{ message }</p>, which renders to, <p>Hello World!</p>.

Note: Inline python blocks are only rendered in a Text element or inside an html attribute.

Multiline blocks are a lot like inline python blocks, but they also have some differences. You can do whatever you like inside this block, however if you expect a value to come from the block you must have at least one local variable. The last local variable defined in this block is used at the result/value.

Conditional rendering with py-if, py-elif, and py-else is an extremely helpful tool in phml. py-if can be used alone and that the python inside it's value must be truthy for the element to be rendered. py-elif requires an element with a py-if or py-elif attribute immediately before it, and it's condition is rendered the same as py-if but only rendered if a py-if or py-elif first fails. py-else requires there to be either a py-if or a py-else immediately before it. It only renders if the previous element's condition fails. If py-elif or py-else is on an element, but the previous element isn't a py-if or py-elif then an exception will occur. Most importantly, the first element in a chain of conditions must be a py-if. For ease of use, instead of writing py-if, py-elif, or py-else can be written as @if, @elif, or @else respectively.

Other than conditions, there is also a built in py-for attribute. Any element with py-for will take a python for-loop expression that will be applied to that element. So if you did something like this:

<ul>
    <li @for='i in range(3)'>
        <p>{i}</p>
    </li>
</ul>

The compiled html will be:

<ul>
    <li>
        <p>1</p>
    </li>
    <li>
        <p>2</p>
    </li>
    <li>
        <p>3</p>
    </li>
</ul>

The for and : in the for loops condition are optional. So you can combine for, i in range(10), and : or leave out for and : at your discretion. py-for can also be written as @for.

Python attributes are shortcuts for using inline python blocks in html attributes. Normally, in phml, you would inject python logic into an attribute similar to this: src="{url('youtube')}". If you would like to make the whole attribute value a python expression you may prefix any attribute with a py- or :. This keeps the attribute name the same after the prefix, but tells the parser that the entire value should be processed as python. So the previous example can also be expressed as py-src="URL('youtube')" or :src="URL('youtube')".

This language also has the ability to convert back to html and json with converting to html having more features. Converting to json is just a json representation of a phml ast. However, converting to html is where the magic happens. The compiler executes python blocks, substitutes components, and processes conditions to create a final html string that is dynamic to its original ast. A user may pass additional kwargs to the compiler to expose additional data to the execution of python blocks. If you wish to compile to a non supported language the compiler can take a callable that returns the final string. It passes all the data; components, kwargs, ast, etc… So if a user wishes to extend the language thay may.

:warning: This language is in early planning and development stages. All forms of feedback are encouraged.

How to use

PHML is in early planning so the use is limited.

The current version is able to parse phml using an html parser. This creates a phml ast which then can be converted back to phml for to json. Converting to html is coming soon, but will take type since that is the core functionality of this language. It will need to parse, execute, and handle imbedded python code.

Use

PHML provides file type variables for better ease of use. The types include HTML, PHML, JSON, and XML. They can be used with the import from phml import Formats. Then all you need to do is use Formats.HTML or any other format.

First import the core parser and compiler, from phml import PHML. Then you can do the following:

phml = PHML().load("path/to/file.phml")
print(core.render())

There is method chaining so most if not all methods can be chained. The obvious exception being any method that returns a value.

By default PHML.render() will return the html string. If you want to get a json string you may pass Formats.JSON. PHML.render(file_type=Formats.JSON).

If you want to write to a file you can call core.write("path/to/output/file.phml"). Same with render it defaults to html. You can change this the same way as render. core.write("path/to/otuput/file.json", file_type=Formats.JSON).

For both render and write you will first need to call core.load("path/to/source/file.phml"). This parses the source file and stores the ast in the parser. render and write then use that ast to create the desired output. Optionally if you already have a phml or html string or a properly formatted dict you can call core.parse(data) which will parse that information similar to load.

Every time core.parse or core.load is called it will overwrite the stored ast variable.

There are many for features such as globally exposed variables or the ability to add nested scopes for importing objects inside of a phml document.

For more information check out the API Docs

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

phml-0.2.1.tar.gz (1.8 MB view hashes)

Uploaded Source

Built Distribution

phml-0.2.1-py3-none-any.whl (79.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