Skip to main content

npf-renderer

A Python library for rendering Tumblr's Neue Post Format (NPF) into HTML

Output

Example output

Usage:

import pytumblr
import npf_renderer

client = pytumblr.TumblrRestClient(*TUMBLR_API_KEYS)

blog = client.posts(BLOG_NAME, npf=True)
post = blog["posts"][0]

content, layout = post["content"], post["layout"]

has_error, post_html = npf_renderer.format_npf(content, layout, pretty_html=True)

print(post_html)
HTML
<div class="post-body">
  <div class="layout-row">
    <p class="text-block">
      <span class="inline-formatted-content">This is a <i class="inline-italics">text block</i>! I have a 
        <b class="inline-bold">lot</b> of inline formatting options! 
        <span class="inline-color" style="color: #ff4930;">Here's some text in </span>
        <span class="inline-color" style="color: #00b8ff;">color</span>
      </span>
    </p>
  </div>
  <div class="layout-row">
    <figure class="image-block">
      <div class="image-container">
        <img alt="image" class="image" loading="lazy" sizes="(max-width: 540px) 33vh, 180px" srcset="...">
      </div>
    </figure>
    <figure class="image-block">
      <div class="image-container">
        <img alt="image" class="image" loading="lazy" sizes="(max-width: 540px) 33vh, 180px" srcset="...">
      </div>
    </figure>
    <figure class="image-block">
      <div class="image-container">
        <img alt="image" class="image" loading="lazy" sizes="(max-width: 540px) 33vh, 180px" srcset="...">
      </div>
    </figure>
  </div>
  <div class="layout-row">
    <figure class="image-block">
      <div class="image-container">
        <img alt="image" class="image" loading="lazy" sizes="(max-width: 540px) 50vh, 270px" srcset="...">
      </div>
    </figure>
    <figure class="image-block">
      <div class="image-container">
        <img alt="image" class="image" loading="lazy" sizes="(max-width: 540px) 50vh, 270px" srcset="...">
      </div>
    </figure>
  </div>
  <div class="layout-row">
    <div class="link-block">
      <a class="link-block-link" href="https://href.li/?https://example.com">
        <div class="link-block-title">
          <span>Example Domain</span>
        </div>
        <div class="link-block-description-container">
          <div class="link-block-subtitles">
            <span>
              <span>example.com</span>
            </span>
          </div>
        </div>
      </a>
    </div>
  </div>
  <div class="layout-row">
    <p class="text-block">This is a link</p>
  </div>

Output

Example output


Make sure to import the CSS from npf_renderer.utils.BASIC_LAYOUT_CSS!

with open("basic_layout.css", "w") as file:
    file.write(npf_renderer.utils.BASIC_LAYOUT_CSS)
<link rel="stylesheet" type="text/css" href="basic_layout.css">

format_npf will return placeholder HTML for any blocks it doesn't support.

Unsupported blocks
<div class="post-body">
  <p class="text-block"> This text block is supported but the next block is not! </p>
  <div class="unsupported-content-block">
    <div class="unsupported-content-block-message">
      <h1>Unsupported content placeholder</h1>
      <p>Hello! I'm a placeholder for the unsupported "unsupported" type NPF content block. Please report me!</p>
    </div>
  </div>
</div>

In the event that it cannot format anything an empty div will be returned


Installation

pip install npf-renderer

Advanced

URL Handling

You can pass in a custom URL handler function to format_npf to replace any links within the NPF tree.

def url_handler(url):
    url = urllib.parse.urlparse(url)

    if url.hostname.endswith("example.com"):
        return url._replace(netloc="other.example.com").geturl()

format_npf(contents, layouts, url_handler=url_handler)

Polls

As polls require an additional request in order to fetch results, npf-renderer by default can only render a very basic poll without any votes attached.

You can however provide the data necessary for npf-renderer to populate polls by passing in a callback function to format_npf that takes a poll_id argument.

Be sure to have the blog name and the post ID at hand too, as Tumblr's API requires all three to fetch poll results.

The data returned should be in the form:

{
  "results": {
    // answer_id => vote_count
    "9a025e86-2f02-452e-99d3-b4c0fd9afd48": 123,
    "fad65faf-06d3-4a24-85a9-47c096ab07e3": 321
  },
  "timestamp": 1706642448
}

Example:

def create_callback(blog_name, post_id)
    def poll_callback(poll_id):
        initial_results = request_poll_results(blog_name, post_id, poll_id)

        return initial_results["response"]

    return poll_callback

npf_renderer.format_npf(content, layout, poll_result_callback=create_callback(blog_name, post_id))

Features

(True as of master branch)

  • Text blocks

  • Image blocks

  • Link Blocks

  • Audio Blocks

  • Video Blocks

  • Polls Blocks

  • Layouts

  • Attributions

Metadata

Release files for npf-renderer 0.13.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for npf-renderer 0.13.0
File Size Uploaded
npf_renderer-0.13.0.tar.gz 29.8 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for npf-renderer 0.13.0
File Interpreter ABI Platform
npf_renderer-0.13.0-py3-none-any.whl Python 3 none any Details

Total release size: 66.2 kB

Release files / npf_renderer-0.13.0.tar.gz

Download URL npf_renderer-0.13.0.tar.gz
Size 29.8 kB
Tags Source
SHA-256 checksum
How to use checksums
bbbe477c478d0258424f08096f70ded453d72ab88d0a7f54c24788a810c1c204
BLAKE2b-256 checksum
How to use checksums
2455fc7fe4cf1ed46b628b1dee4d5d155cfabf7cebf0a006f78aeaf139929a99
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.1.0 CPython/3.12.8

Release files / npf_renderer-0.13.0-py3-none-any.whl

Download URL npf_renderer-0.13.0-py3-none-any.whl
Size 36.3 kB
Tags Python 3
SHA-256 checksum
How to use checksums
5d870dbc1fe51ea13cc2979456622621e88576adfc2c084647560c49f8d5654c
BLAKE2b-256 checksum
How to use checksums
084fbf6e218f1e6d1f4222a47fbfca733e8a1d60b950f26dcf892041bb3619c9
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.1.0 CPython/3.12.8

Release history Release notifications | RSS feed

This release

0.13.0 This release

2 release files

0.12.1

2 release files

0.11.1

2 release files

0.10.0

2 release files

0.9.0

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page