Skip to content

Instantly share code, notes, and snippets.

@mahemoff
Created February 5, 2025 04:47
Show Gist options
  • Save mahemoff/a65fbc39430a10fdd181c3f9e599253f to your computer and use it in GitHub Desktop.
Save mahemoff/a65fbc39430a10fdd181c3f9e599253f to your computer and use it in GitHub Desktop.

Purpose

Save your Pinboard bookmarks as a markdown table. I'm using this to export bookmarks from Pinboard to Obsidian.

The resulting table looks like this:

Bookmark Date Tags
Phind: AI search engine 2023-04-17 ai, query-tool
Perplexity AI: Ask Anything 2023-02-08 ai, query-tool
AI Tools | Braiain 2023-02-06 ai, app-catalogue
f/awesome-chatgpt-prompts: This repo includes ChatGPT prompt curation to use ChatGPT better. 2023-02-06 prompt-engineering, ai

Usage

  1. Login to Pinboard
  2. Download the JSON export from https://pinboard.in/export/ (Direct download link: https://pinboard.in/export/format:json/)
  3. python3 pinboard_json_to_markdown.py < pinboard_export.json > pinboard.md
#!/usr/bin/env python3
import sys
import json
import datetime
import html
def sanitize(text):
"""
Escape HTML tags and special characters so that no HTML is output in any column.
Also escapes pipe characters for safe inclusion in a Markdown table.
"""
# First escape HTML entities (including <, >, and quotes)
escaped = html.escape(text, quote=True)
# Then escape pipe characters to avoid breaking the Markdown table
return escaped.replace("|", "\\|")
def main():
# Load the JSON data from standard input
data = json.load(sys.stdin)
# Print the Markdown table header
print("| Bookmark | Date | Tags |")
print("| -------- | ---- | ---- |")
for item in data:
raw_url = item.get("href", "")
# Use the URL as fallback if description is empty
raw_description = item.get("description", "") or raw_url
raw_time = item.get("time", "")
raw_tags = item.get("tags", "")
# Convert time to a date in the format YYYY-MM-DD
try:
dt = datetime.datetime.strptime(raw_time, "%Y-%m-%dT%H:%M:%SZ")
date = dt.strftime("%Y-%m-%d")
except ValueError:
date = raw_time[:10] if raw_time else ""
# Sanitize URL, description, and tags
safe_url = sanitize(raw_url)
safe_description = sanitize(raw_description)
# Wrap the URL in angle brackets within the inline Markdown link to help parsers handle special characters
bookmark = f"[{safe_description}](<{safe_url}>)"
if raw_tags:
# Split tags on whitespace, sanitize each, then join with commas
tags = ", ".join(sanitize(tag) for tag in raw_tags.split())
else:
tags = ""
# Print the Markdown table row
print(f"| {bookmark} | {date} | {tags} |")
if __name__ == '__main__':
main()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment