A Python macro in bDS is a small script that automatically generates its own HTML content when rendering a post. In this post, we will build a macro together that creates a colored tag cloud β step by step, from the first "Hello World" to the finished visualization.
What we build
A tag cloud that displays all the tags of the blog. Each tag is labeled with the number of its posts. The color is determined by the frequency: rarely used tags appear in blue, frequently used ones in red β in between are green and yellow.
Step 1: Create a new script
In the sidebar of bDS, you will find the Scripts section. Click on New Script there.
In the editor, you will now see several fields:
- Title β Give your script a name, e.g.
Awesome-Tag-Cloud - Slug β Automatically generated, e.g.
awesome_tag_cloud. Under this name, you will later call the macro in the post - Type β Select macro here
- Entry point β Select main (automatically recognized as soon as you have a function
mainin the code) - Activated β Check the box so that the macro is also executed during rendering
Step 2: A minimal macro
Enter the following code in the Script content area:
async def main(context, post_data):
return {
'html': '<p>Hello from the macro!</p>'
}
Click on Save Script. You can test with Check Syntax whether the code is error-free.
To use the macro in a post, simply write at the desired location:
[[awesome_tag_cloud]]
When rendering, this placeholder is replaced by the HTML text β in this case simply "Hello from the macro!".
Step 3: Determine tags and post numbers
Now we expand the script. Via the built-in interface bds_api, the macro can access all the data of the blog. We load all tags and all posts and count how often each tag is used:
from bds_api import bds
async def main(context, post_data):
# Load all tags
tags = await bds.tags.get_all()
# Load all posts
result = await bds.posts.get_all()
posts = result['items']
# Count how often each tag occurs
counter = {}
for post in posts:
for tag in post.get('tags', []):
counter[tag] = counter.get(tag, 0) + 1
# Output as text for control
lines = []
for tag in tags:
name = tag['name']
count = counter.get(name, 0)
lines.append(f'{name}: {count} post/posts')
return {
'html': '<br>'.join(lines)
}
After saving, the macro displays a simple list when rendering: each tag with the number of its posts.
Step 4: The tag cloud as a colored representation
In the last step, we convert the output into a real tag cloud. The tags are displayed in different sizes and colors β depending on the frequency. The color scale ranges from blue (few posts) via green and yellow to red (many posts).
from bds_api import bds
async def main(context, post_data):
tags = await bds.tags.get_all()
result = await bds.posts.get_all()
posts = result['items']
counter = {}
for post in posts:
for tag in post.get('tags', []):
counter[tag] = counter.get(tag, 0) + 1
# Determine the range of frequencies
values = [counter.get(t['name'], 0) for t in tags]
if not values or max(values) == 0:
return {'html': '<p>No tags with posts found.</p>'}
min_val = min(values)
max_val = max(values)
span = max_val - min_val if max_val != min_val else 1
# Calculate color on the scale blue β green β yellow β red
def color_for(share):
if share < 0.33:
# Blue β Green
t = share / 0.33
r = 0
g = int(128 + 127 * t)
b = int(200 * (1 - t))
elif share < 0.66:
# Green β Yellow
t = (share - 0.33) / 0.33
r = int(255 * t)
g = 220
b = 0
else:
# Yellow β Red
t = (share - 0.66) / 0.34
r = 220
g = int(200 * (1 - t))
b = 0
return f'rgb({r},{g},{b})'
# Build HTML
elements = []
for tag in tags:
name = tag['name']
count = counter.get(name, 0)
share = (count - min_val) / span
size = 0.8 + share * 1.6 # 0.8em to 2.4em
color = color_for(share)
elements.append(
f'<span style="font-size:{size:.1f}em;color:{color};'
f'padding:4px 8px;display:inline-block;cursor:default" '
f'title="{count} post(s)">'
f'{name} <sup style="font-size:0.6em">({count})</sup></span>'
)
html = (
'<div style="line-height:2.2;text-align:center;'
'padding:16px;border:1px solid #e0e0e0;border-radius:8px">'
+ ' '.join(elements)
+ '</div>'
)
return {'html': html}
How the coloring works
The color is calculated based on the share β i.e., how the frequency of a tag compares to all others:
| Share | Color |
|---|---|
| 0 % β 33 % | Blue β Green |
| 33 % β 66 % | Green β Yellow |
| 66 % β 100 % | Yellow β Red |
Tags with few posts are therefore rather cool (blue), frequently used tags rather warm (red). In addition, the font size is adjusted: rare tags appear smaller, frequent ones larger.
Summary
| Step | What happens |
|---|---|
| Create a new script | Via Scripts β New Script in the sidebar |
| Select type | Set Type to macro |
| Write code | In the Script content area |
| Activate | Check Activated |
| Use in post | Write [[awesome_tag_cloud]] at the desired location |
The macro is executed again with every preview and every publication β the tag cloud is therefore always up to date.