Unofficial Python port of server-side rendering from AMP Optimizer. Tested in Python 3.8 and above, but works on Python 3.6+.
AMP Renderer performs the following optimizations:
- Inject the specific layout markup into each AMP element
- Insert the AMP runtime styles into the document
- Remove the AMP boilerplate styles, if possible
- Mark the document as “transformed” with the appropriate tags on the
html
element - Insert
img
tags for images with the data-hero attribute
It also makes these formatting updates:
- Remove empty
class
andstyle
tags for AMP HTML elements - Convert tag names and attribute names to lowercase
- Convert numerical attribute values to strings
- Use double quotes ("") for attributes, and escape double quotes inside attribute values
- Remove whitespace between html attributes
- If desired, removes comments (disabled by default)
- If desired, trims whitespace around HTML attribute values (disabled by default, and not always a good idea)
AMPRenderer can be used on a block of arbitrary HTML, but when used on a full document, it will insert the AMP runtime styles and, if possible, remove the AMP boilerplate styles.
Boilerplate styles can be removed except in these cases:
- An AMP element uses an unsupported value for the
layout
attribute amp-audio
is used- There is at least one
amp-experiment
active - Transformation fails for one or more elements due to an invalid attribute value for
media
,sizes
, orheights
- Any render-delaying extension is used. Currently this means:
amp-dynamic-css-classes
amp-story
If boilerplate styles can’t be removed, the attribute no_boilerplate
will be set to True
after calling render
; otherwise it will be False
. Until render
runs, the no_boilerplate
attribute isn’t set at all.
If using Django, you can use the Django AMP Renderer middleware.
Otherwise, install via PyPI:
pip install amp-renderer
Minimal usage:
from amp_renderer import AMPRenderer
...
RUNTIME_VERSION = "012345678" /* Current AMP runtime version number */
RUNTIME_STYLES = "..." /* Current contents of https://cdn.ampproject.org/v0.css */
renderer = AMPRenderer(
runtime_version=RUNTIME_VERSION,
runtime_styles=RUNTIME_STYLES)
original_html = """
<!doctype html>
<html ⚡>
...
</html>
"""
result = renderer.render(original_html)
print(result)
Remove comments and/or trim attributes:
renderer.strip_comments = True
renderer.trim_attributes = True
result = renderer.render(original_html)
print(result)
The AMPRenderer class inherits from HTMLParser, and can be similarly extended.
Install development requirements (Requires Python >= 3.8):
make install
Sort imports:
make format
Lint:
make lint
Test:
make test
There are still some aspects of the official AMP Optimizer implementation that haven’t been addressed yet. PRs welcome.
-
Tested against AMP Optimizer’s ServerSideRendering spec - Automatic runtime version management
-
Supportsizes
,media
, andheights
via CSS injection -
Group CSS injections formedia
attributes by shared media queries to reduce necessary bytes - Support percent values in
heights
- Warn or fail if CSS injection puts the
amp-custom
element over the byte limit
-
Injectimg
tag foramp-img
s with thedata-hero
attribute - Enforce 2-image limit on
data-hero
- Autodetect hero images
- Support hero image functionality for
amp-iframe
,amp-video
, andamp-video-iframe
The Python AMP Renderer does not insert preload
links into the head
of the DOM object for hero images; This can be done by hand for more control over the critical path.