Skip to content

Instantly share code, notes, and snippets.

@mikeckennedy
Created November 23, 2022 18:46
Show Gist options
  • Save mikeckennedy/20a205602111ac32dbfb61544f15a488 to your computer and use it in GitHub Desktop.
Save mikeckennedy/20a205602111ac32dbfb61544f15a488 to your computer and use it in GitHub Desktop.
Python script to build a tag cloud for Hugo websites
# You need to write a topics_template.md file with the [TOPIC_CLOUD] in the location to have the tag cloud injected.
# You also need to add topics.md to your config.toml for Hugo.
# This will read content/posts/*.md and pull out 'tags' from the frontmatter section to create topics.md
from collections import Counter
import json
from pathlib import Path
def main():
topics = count_topics()
tag_text = build_tag_text(topics)
text = get_template_text()
new_topics_text = text.replace('[TOPIC_CLOUD]', tag_text)
write_topics_file(new_topics_text)
print("Wrote to topics.md")
def write_topics_file(topics_text: str):
topics_file = Path(__file__).parent.parent / "mksite" / "content" / "topics.md"
topics_file.write_text(topics_text)
def build_tag_text(topics: list[str]):
c = Counter(topics)
counted_topics = c.most_common()
print("Generated topics list:")
print(counted_topics)
text = ""
max_count = max(ct[1] for ct in counted_topics)
min_count = min(ct[1] for ct in counted_topics)
max_em = 2.5
min_em = .75
for tag, count in counted_topics:
tag = tag.replace(' ', '-').lower().strip()
ratio = count/(max_count-min_count)
em = (max_em - min_em)*ratio
# text += f"- [{count}] [{tag}](/tags/{tag}/)\n"
text += f'<a style="margin: 10px; font-size: {em}em;" class="badge-tag tag badge" href="/tags/{tag}/">{tag}</a>'
return text
def count_topics() -> list[str]:
all_tags = []
posts_folder = Path(__file__).parent.parent / "mksite" / "content" / "posts"
for file in posts_folder.glob("*.md"):
tags = get_tags_from_file(file)
all_tags.extend(tags)
all_tags.sort()
return all_tags
def get_tags_from_file(file: Path) -> list[str]:
for line in file.read_text().splitlines():
if line.startswith("tags: ["):
fake_json = '{"tags": ' + line[5:].replace("'", '"') + "}"
tags = json.loads(fake_json)["tags"]
return tags
return []
def get_template_text() -> str:
template_file = Path(__file__).parent / "topics_template.md"
template_md = template_file.read_text()
return template_md
if __name__ == "__main__":
main()
@mikeckennedy
Copy link
Author

Here's the topics template markdown:

---
title: "Topics"
draft: false
---

Looking to explore the articles? I built a tag cloud of topics. Dive in! ;)

[TOPIC_CLOUD]

@mikeckennedy
Copy link
Author

See it in action at https://mkennedy.codes/topics/

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment