u84u/palestine

python DOM and SSR HTML rendering library

1

stars

44

commits

Python

primary language

Sep 9, 2026

updated

pypi.org/project/palestine/
dom
html
html5
html-template
palestine
stdlib
stdlib-only
stdlib-python
web
webapp
web-development
website
websocket
Browse cluster: HTML Parsing and DOM Manipulation

README

Palestine

A Python library for building and rendering HTML using a DOM and component model.

Installation

pip install git+https://github.com/u84u/palestine.git

Or clone and install locally:

git clone https://github.com/u84u/palestine
cd palestine
pip install -e .

Requires Python 3.9+.

Quick start

from palestine import Document, Html, Body, Div, Text

doc = Document()
html = Html()
body = Body()
doc.append_child(html)
html.append_child(body)

page = Div(class_="container")
page.append_child(Text("Hello from Palestine"))
body.append_child(page)

print(doc)

Output:

<!DOCTYPE html>
<html><body><div class="container">Hello from Palestine</div></body></html>

What it looks like

Build a DOM tree

from palestine import Div, Text, Button

card = Div(class_="card")
card.append_child(Text("Title"))
card.append_child(Button(type="submit").append_child(Text("Click")))

# Move nodes between parents automatically
other = Div()
other.append_child(card)  # Detaches from previous parent

Render HTML

from palestine import Div, Text, RawText

# Text is escaped automatically
div = Div()
div.append_child(Text("<script>"))  # Renders as &lt;script&gt;

# RawText is for trusted markup
div.append_child(RawText("<svg>...</svg>"))  # Renders as-is

Compose components

from palestine import Div, H1, P, Text

def Card(title, content):
    card = Div(class_="card")
    card.append_child(H1().append_child(Text(title)))
    card.append_child(P().append_child(Text(content)))
    return card

page = Div()
page.append_child(Card("First", "Content here"))
page.append_child(Card("Second", "More content"))

Parse and manipulate HTML

from palestine import parse_html

doc = parse_html('<div class="box"><p>Hello</p></div>')
div = doc.query_selector(".box")
div.append_child(parse_html("<span>World</span>"))

Templates

from palestine import Template

tmpl = Template("<h1>{{ title }}</h1><p>{{ content }}</p>")
html = tmpl.render(title="My Page", content="Hello world")

Forms and validation

from palestine import FormBuilder, FormValidator, Required, Email

form = FormBuilder(action="/submit", method="post")
form.add_text("name", "Name", required=True)
form.add_email("email", "Email", required=True)
form.add_submit("Register")

validator = FormValidator({
    "name": [Required()],
    "email": [Required(), Email()],
})
errors = validator.validate({"name": "", "email": "invalid"})

Features

  • DOM primitives: Node, Element, Text, RawText, Comment, Document
  • HTML elements: All standard HTML5 elements
  • Rendering: HTML serialization, pretty printing, minification, streaming
  • Parsing: HTML to DOM conversion
  • Templates: Variable substitution and control flow
  • Components: Reusable UI composition
  • Forms: Form building and validation
  • Security: HTML sanitization, escaping, URL validation
  • VDOM: Virtual DOM with diff/patch

Architecture

Palestine is built around a mutable DOM tree:

Node
  ├── Element (tag, attributes, children)
  ├── Text (escaped content)
  ├── RawText (trusted markup)
  ├── Comment
  └── Document (root node)

Components are functions that compose elements. The renderer serializes the tree to HTML.

Performance

Palestine's renderer is optimized around direct DOM traversal, string accumulation, and bounded selector caching.

Reproducible benchmarks, profiling scripts, and historical baseline comparisons live in the GitHub repository under benchmarks/.

From a Git checkout:

python -m benchmarks.benchmark
python -m benchmarks.benchmark_memory
python benchmarks/profile_hotpaths.py

See benchmarks/REPORT.md for detailed results and methodology.

Status

Early-stage project. The core DOM, rendering, and template engine are functional and tested.

The parser is built on Python's html.parser and does not implement the full WHATWG HTML parsing algorithm. It handles common cases but may differ from browser parsing on malformed input.

The API may change between versions.

Why Palestine?

Most Python HTML generation falls into two camps: template languages (Jinja2, Mako) that treat HTML as strings, or minimal builder libraries (dominate, htpy) with a narrow API.

Palestine is different in that it gives you a mutable, traversable DOM tree — the same conceptual model as the browser — with querySelector, classList, event dispatch, innerHTML, closest, and clone. If you are building a server-side rendering pipeline, a static site generator, or an email renderer where you need to inspect and mutate the tree after construction (not just write it once), Palestine is designed for that.

It has no runtime dependencies and works on Python 3.9+.

Examples

Two runnable examples are in the examples/ directory:

  • hello_world.py — minimal HTTP server
  • file_explorer.py — file browser showing table building, conditional DOM construction, and safe path handling

Run either with: python examples/file_explorer.py Then open http://localhost:8000

License

MIT

Contributors

u84u

44 commits

u84u/palestine

python DOM and SSR HTML rendering library

1

stars

44

commits

Python

primary language

Sep 9, 2026

updated

pypi.org/project/palestine/
dom
html
html5
html-template
palestine
stdlib
stdlib-only
stdlib-python
web
webapp
web-development
website
websocket
Browse cluster: HTML Parsing and DOM Manipulation

README

Palestine

A Python library for building and rendering HTML using a DOM and component model.

Installation

pip install git+https://github.com/u84u/palestine.git

Or clone and install locally:

git clone https://github.com/u84u/palestine
cd palestine
pip install -e .

Requires Python 3.9+.

Quick start

from palestine import Document, Html, Body, Div, Text

doc = Document()
html = Html()
body = Body()
doc.append_child(html)
html.append_child(body)

page = Div(class_="container")
page.append_child(Text("Hello from Palestine"))
body.append_child(page)

print(doc)

Output:

<!DOCTYPE html>
<html><body><div class="container">Hello from Palestine</div></body></html>

What it looks like

Build a DOM tree

from palestine import Div, Text, Button

card = Div(class_="card")
card.append_child(Text("Title"))
card.append_child(Button(type="submit").append_child(Text("Click")))

# Move nodes between parents automatically
other = Div()
other.append_child(card)  # Detaches from previous parent

Render HTML

from palestine import Div, Text, RawText

# Text is escaped automatically
div = Div()
div.append_child(Text("<script>"))  # Renders as &lt;script&gt;

# RawText is for trusted markup
div.append_child(RawText("<svg>...</svg>"))  # Renders as-is

Compose components

from palestine import Div, H1, P, Text

def Card(title, content):
    card = Div(class_="card")
    card.append_child(H1().append_child(Text(title)))
    card.append_child(P().append_child(Text(content)))
    return card

page = Div()
page.append_child(Card("First", "Content here"))
page.append_child(Card("Second", "More content"))

Parse and manipulate HTML

from palestine import parse_html

doc = parse_html('<div class="box"><p>Hello</p></div>')
div = doc.query_selector(".box")
div.append_child(parse_html("<span>World</span>"))

Templates

from palestine import Template

tmpl = Template("<h1>{{ title }}</h1><p>{{ content }}</p>")
html = tmpl.render(title="My Page", content="Hello world")

Forms and validation

from palestine import FormBuilder, FormValidator, Required, Email

form = FormBuilder(action="/submit", method="post")
form.add_text("name", "Name", required=True)
form.add_email("email", "Email", required=True)
form.add_submit("Register")

validator = FormValidator({
    "name": [Required()],
    "email": [Required(), Email()],
})
errors = validator.validate({"name": "", "email": "invalid"})

Features

  • DOM primitives: Node, Element, Text, RawText, Comment, Document
  • HTML elements: All standard HTML5 elements
  • Rendering: HTML serialization, pretty printing, minification, streaming
  • Parsing: HTML to DOM conversion
  • Templates: Variable substitution and control flow
  • Components: Reusable UI composition
  • Forms: Form building and validation
  • Security: HTML sanitization, escaping, URL validation
  • VDOM: Virtual DOM with diff/patch

Architecture

Palestine is built around a mutable DOM tree:

Node
  ├── Element (tag, attributes, children)
  ├── Text (escaped content)
  ├── RawText (trusted markup)
  ├── Comment
  └── Document (root node)

Components are functions that compose elements. The renderer serializes the tree to HTML.

Performance

Palestine's renderer is optimized around direct DOM traversal, string accumulation, and bounded selector caching.

Reproducible benchmarks, profiling scripts, and historical baseline comparisons live in the GitHub repository under benchmarks/.

From a Git checkout:

python -m benchmarks.benchmark
python -m benchmarks.benchmark_memory
python benchmarks/profile_hotpaths.py

See benchmarks/REPORT.md for detailed results and methodology.

Status

Early-stage project. The core DOM, rendering, and template engine are functional and tested.

The parser is built on Python's html.parser and does not implement the full WHATWG HTML parsing algorithm. It handles common cases but may differ from browser parsing on malformed input.

The API may change between versions.

Why Palestine?

Most Python HTML generation falls into two camps: template languages (Jinja2, Mako) that treat HTML as strings, or minimal builder libraries (dominate, htpy) with a narrow API.

Palestine is different in that it gives you a mutable, traversable DOM tree — the same conceptual model as the browser — with querySelector, classList, event dispatch, innerHTML, closest, and clone. If you are building a server-side rendering pipeline, a static site generator, or an email renderer where you need to inspect and mutate the tree after construction (not just write it once), Palestine is designed for that.

It has no runtime dependencies and works on Python 3.9+.

Examples

Two runnable examples are in the examples/ directory:

  • hello_world.py — minimal HTTP server
  • file_explorer.py — file browser showing table building, conditional DOM construction, and safe path handling

Run either with: python examples/file_explorer.py Then open http://localhost:8000

License

MIT

Contributors

u84u

44 commits

Languages

Python

100.0%