HTML renderer for Sanity's Portable Text format
Project description
Portable Text HTML Renderer for Python
This package generates HTML from Portable Text.
For the most part, it mirrors Sanity's own block-content-to-html NPM library.
Installation
pip install portabletext-html
Usage
Instantiate the PortableTextRenderer
class with your content and call the render
method.
The following content
from portabletext_html import PortableTextRenderer
renderer = PortableTextRenderer({
"_key": "R5FvMrjo",
"_type": "block",
"children": [
{"_key": "cZUQGmh4", "_type": "span", "marks": ["strong"], "text": "A word of"},
{"_key": "toaiCqIK", "_type": "span", "marks": ["strong"], "text": " warning;"},
{"_key": "gaZingsA", "_type": "span", "marks": [], "text": " Sanity is addictive."}
],
"markDefs": [],
"style": "normal"
})
renderer.render()
Generates this HTML
<p><strong>A word of warning;</strong> Sanity is addictive.</p>
Supported types
The block
and span
types are supported out of the box.
Custom types
Beyond the built-in types, you have the freedom to provide
your own serializers to render any custom _type
the way you
would like to.
To illustrate, if you passed this data to the renderer class:
from portabletext_html import PortableTextRenderer
renderer = PortableTextRenderer({
"_type": "block",
"_key": "foo",
"style": "normal",
"children": [
{
"_type": "span",
"text": "Press, "
},
{
"_type": "button",
"text": "here"
},
{
"_type": "span",
"text": ", now!"
}
]
})
renderer.render()
The renderer would actually throw an error here, since button
does not have a corresponding built-in type serializer by default.
To render this text you must provide your own serializer, like this:
from portabletext_html import PortableTextRenderer
def button_serializer(node: dict, context: Optional[Block], list_item: bool):
return f'<button>{node["text"]}</button>'
renderer = PortableTextRenderer(
...,
custom_serializers={'button': button_serializer}
)
output = renderer.render()
With the custom serializer provided, the renderer would now successfully output the following HTML:
<p>Press <button>here</button>, now!</p>
Supported mark definitions
The package provides several built-in marker definitions and styles:
decorator marker definitions
em
strong
code
underline
strike-through
annotation marker definitions
link
comment
Custom mark definitions
Like with custom type serializers, additional serializers for marker definitions and styles can be passed in like this:
from portabletext_html import PortableTextRenderer
renderer = PortableTextRenderer(
...,
custom_marker_definitions={'em': ComicSansEmphasis}
)
renderer.render()
The primary difference between a type serializer and a mark definition serializer is that the latter uses a class structure, and has three required methods.
Here's an example of a custom style, adding an extra font to the built-in equivalent serializer:
from portabletext_html.marker_definitions import MarkerDefinition
class ComicSansEmphasis(MarkerDefinition):
tag = 'em'
@classmethod
def render_prefix(cls, span: Span, marker: str, context: Block) -> str:
return f'<{cls.tag} style="font-family: "Comic Sans MS", "Comic Sans", cursive;">'
@classmethod
def render_suffix(cls, span: Span, marker: str, context: Block) -> str:
return f'</{cls.tag}>'
@classmethod
def render_text(cls, span: Span, marker: str, context: Block) -> str:
# custom rendering logic can be placed here
return str(span.text)
@classmethod
def render(cls, span: Span, marker: str, context: Block) -> str:
result = cls.render_prefix(span, marker, context)
result += str(span.text)
result += cls.render_suffix(span, marker, context)
return result
Since the render_suffix
and render
methods here are actually identical to the base class,
they do not need to be specified, and the whole example can be reduced to:
from portabletext_html.marker_definitions import MarkerDefinition # base
from portabletext_html import PortableTextRenderer
class ComicSansEmphasis(MarkerDefinition):
tag = 'em'
@classmethod
def render_prefix(cls, span: Span, marker: str, context: Block) -> str:
return f'<{cls.tag} style="font-family: "Comic Sans MS", "Comic Sans", cursive;">'
renderer = PortableTextRenderer(
...,
custom_marker_definitions={'em': ComicSansEmphasis}
)
renderer.render()
Supported styles
Blocks can optionally define a style
tag. These styles are supported:
h1
h2
h3
h4
h5
h6
blockquote
normal
Missing features
For anyone interested, we would be happy to see a
default built-in serializer for the image
type added.
In the meantime, users should be able to serialize image types by passing a custom serializer.
Contributing
Contributions are always appreciated 👏
For details, see the CONTRIBUTING.md.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
File details
Details for the file portabletext-html-1.1.3.tar.gz
.
File metadata
- Download URL: portabletext-html-1.1.3.tar.gz
- Upload date:
- Size: 15.0 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: poetry/1.1.6 CPython/3.9.13 Linux/5.13.0-1029-azure
File hashes
Algorithm | Hash digest | |
---|---|---|
SHA256 | cdf8237aa720d71d38017ad80c27b0fe0a70732f30093ed741697b9f3a0f0cff |
|
MD5 | 92a7ec705877bdc43c58dad633dbd9e6 |
|
BLAKE2b-256 | f9acd89fc1c925f4d501a7c31400c5f68b692e986b487ada0a7a0322dda53324 |
File details
Details for the file portabletext_html-1.1.3-py3-none-any.whl
.
File metadata
- Download URL: portabletext_html-1.1.3-py3-none-any.whl
- Upload date:
- Size: 15.0 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: poetry/1.1.6 CPython/3.9.13 Linux/5.13.0-1029-azure
File hashes
Algorithm | Hash digest | |
---|---|---|
SHA256 | 1e87a1d60e7371bb39484db636e9a4ab35820d94a1a1c3bf8985a22d42853039 |
|
MD5 | 8a798cd5454943a955d14dcaf6710f82 |
|
BLAKE2b-256 | d68d7b27041d2c69744bc4b14ed7bf5bf7b6aa39ee4b2f77525c6c68ef9932b4 |