From 209a79bae34c14e8ee4f55c5ca52a8e8a70d7814 Mon Sep 17 00:00:00 2001 From: Claude Date: Tue, 30 Dec 2025 01:38:19 +0000 Subject: [PATCH] Add meta/ directory with JSON metadata for each tool - Created docs_to_json.py script to convert *.docs.md files to JSON - Each tool now has a meta/.json file with description and commit hash - Updated build_colophon.py, gather_links.py, build_by_month.py to read from meta/ JSON files - Updated write_docs.py to also generate meta/ JSON files when creating docs haiku.json intentionally omitted to test rebuild capability --- build_by_month.py | 45 +++------- build_colophon.py | 34 +++----- docs_to_json.py | 84 +++++++++++++++++++ gather_links.py | 29 ++----- meta/ai-adoption.json | 4 + meta/alt-text-extractor.json | 4 + meta/analytics.json | 4 + meta/animated-rainbow-border.json | 4 + meta/annotated-presentations.json | 4 + meta/apsw-query.json | 4 + meta/arena-animated.json | 4 + meta/ares.json | 4 + meta/aria-live-regions.json | 4 + meta/audio-spectrum.json | 4 + meta/avatar-web-component.json | 4 + meta/badge-drawer.json | 4 + meta/badge-repl.json | 4 + meta/base64-gzip-decoder.json | 4 + meta/bbox-cropper.json | 4 + ...ed-cauliflower-and-turkish-style-stew.json | 4 + meta/blog-to-newsletter.json | 4 + meta/bluesky-faves.json | 4 + meta/bluesky-firehose.json | 4 + meta/bluesky-quote-finder.json | 4 + meta/bluesky-resolve.json | 4 + meta/bluesky-search.json | 4 + meta/bluesky-thread.json | 4 + meta/bluesky-timeline.json | 4 + meta/box-shadow.json | 4 + meta/broadcast-channel-chat.json | 4 + meta/bugzilla-bug.json | 4 + meta/bullish-bearish.json | 4 + meta/california-clock-change.json | 4 + meta/census-reporter-claude.json | 4 + meta/census-reporter-gemini.json | 4 + meta/chrome-prompt-playground.json | 4 + meta/claude-code-timeline.json | 4 + meta/claude-token-counter.json | 4 + meta/click-grid-to-expand.json | 4 + meta/clipboard-backup.json | 4 + meta/clipboard-viewer.json | 4 + meta/code-with-claude-2025.json | 4 + meta/codex-timeline.json | 4 + meta/compare-pdfs.json | 4 + meta/cooking-timer.json | 4 + meta/cors-fetch.json | 4 + meta/css-text-wrapping.json | 4 + meta/csv-marker-map.json | 4 + meta/date-calculator.json | 4 + meta/deep-research-viewer.json | 4 + meta/devon-lanes.json | 4 + meta/dot.json | 4 + meta/emoji-identifier.json | 4 + meta/encrypt.json | 4 + meta/escape-entities.json | 4 + meta/event-planner.json | 4 + meta/exif.json | 4 + meta/extract-urls.json | 4 + meta/ffmpeg-crop.json | 4 + meta/flexbox-playground.json | 4 + meta/footnotes-experiment.json | 4 + meta/gemini-bbox.json | 4 + meta/gemini-chat.json | 4 + meta/gemini-image-json.json | 4 + meta/gemini-mask.json | 4 + meta/github-account.json | 4 + meta/github-api-write.json | 4 + meta/github-graphiql.json | 4 + meta/github-issue-to-markdown.json | 4 + meta/github-ratelimit.json | 4 + meta/gpt-4o-audio-player.json | 4 + meta/grid-lanes-polyfill.json | 4 + meta/hacker-news-filtered.json | 4 + meta/hacker-news-histogram.json | 4 + meta/hacker-news-thread-export.json | 4 + meta/hn-comments-for-user.json | 4 + meta/html-preview.json | 4 + meta/huggingface-storage.json | 4 + meta/icon-editor.json | 4 + meta/iframe-api-explorer.json | 4 + meta/iframe-sandbox.json | 4 + meta/image-print.json | 4 + meta/image-resize-quality.json | 4 + meta/image-to-jpeg.json | 4 + meta/image-to-svg.json | 4 + meta/incomplete-json-printer.json | 4 + meta/is-it-a-bird.json | 4 + ...ina-embeddings-image-token-calculator.json | 4 + meta/jina-reader.json | 4 + meta/json-diff.json | 4 + meta/json-schema-builder.json | 4 + meta/json-string-extractor.json | 4 + meta/json-to-markdown-transcript.json | 4 + meta/json-to-yaml.json | 4 + meta/justhtml.json | 4 + meta/keyboard-debug.json | 4 + meta/keyboard-filters.json | 4 + meta/lightning-timer.json | 4 + meta/link-extractor.json | 4 + meta/link-temp.json | 4 + meta/llm-lib.json | 4 + meta/markdown-math.json | 4 + meta/mask-visualizer.json | 4 + meta/mdn-timelines.json | 4 + meta/micropython.json | 4 + meta/microquickjs.json | 4 + meta/nav-for-headings.json | 4 + meta/new-yorker-style.json | 4 + meta/notes-to-markdown.json | 4 + meta/numpy-pyodide-lab.json | 4 + meta/ocr.json | 4 + meta/octave-explainer.json | 4 + meta/omit-needless-words.json | 4 + meta/open-sauce-2025.json | 4 + meta/openai-audio-output.json | 4 + meta/openai-audio.json | 4 + meta/openai-webrtc.json | 4 + meta/openfreemap-demo.json | 4 + meta/passkeys.json | 4 + meta/paste-html-subset.json | 4 + meta/paste-rich-text.json | 4 + meta/percentage-recalculator.json | 4 + meta/pge-outages-hmb.json | 4 + meta/php-deserializer.json | 4 + meta/pipfile.json | 4 + meta/pomodoro.json | 4 + meta/progress.json | 4 + meta/prompt-caching.json | 4 + meta/prompts-js.json | 4 + meta/pyodide-bar-chart.json | 4 + meta/pypi-changelog.json | 4 + meta/qr.json | 4 + meta/query-string-stripper.json | 4 + meta/quickjs.json | 4 + meta/reading-time.json | 4 + meta/render-claude-citations.json | 4 + meta/render-markdown.json | 4 + meta/rich-text-to-markdown.json | 4 + meta/rtf-to-html.json | 4 + meta/schema-dsl.json | 4 + meta/side-panel-dialog.json | 4 + meta/sloccount.json | 4 + meta/social-media-cropper.json | 4 + meta/species-observation-map.json | 4 + meta/speech-synthesis.json | 4 + meta/sql-pretty-printer.json | 4 + meta/sqlite-wasm.json | 4 + meta/svg-progressive-render.json | 4 + meta/svg-render.json | 4 + meta/svg-sandbox.json | 4 + meta/swagger-subset.json | 4 + meta/tacopy-playground.json | 4 + meta/terminal-to-html.json | 4 + meta/text-diff.json | 4 + meta/text-indentation.json | 4 + meta/text-wrap-balance-nav.json | 4 + meta/tiff-orientation.json | 4 + meta/timezones.json | 4 + meta/token-usage.json | 4 + meta/transfer-time.json | 4 + meta/transparent-png.json | 4 + meta/unix-timestamp.json | 4 + meta/user-agent.json | 4 + meta/view-pdf.json | 4 + meta/wikipedia-wikitext.json | 4 + meta/word-counter.json | 4 + meta/writing-style.json | 4 + meta/xml-validator.json | 4 + meta/yaml-explorer.json | 4 + meta/youtube-thumbnails.json | 4 + meta/zip-wheel-explorer.json | 4 + write_docs.py | 55 ++++++++++++ 172 files changed, 838 insertions(+), 77 deletions(-) create mode 100644 docs_to_json.py create mode 100644 meta/ai-adoption.json create mode 100644 meta/alt-text-extractor.json create mode 100644 meta/analytics.json create mode 100644 meta/animated-rainbow-border.json create mode 100644 meta/annotated-presentations.json create mode 100644 meta/apsw-query.json create mode 100644 meta/arena-animated.json create mode 100644 meta/ares.json create mode 100644 meta/aria-live-regions.json create mode 100644 meta/audio-spectrum.json create mode 100644 meta/avatar-web-component.json create mode 100644 meta/badge-drawer.json create mode 100644 meta/badge-repl.json create mode 100644 meta/base64-gzip-decoder.json create mode 100644 meta/bbox-cropper.json create mode 100644 meta/blackened-cauliflower-and-turkish-style-stew.json create mode 100644 meta/blog-to-newsletter.json create mode 100644 meta/bluesky-faves.json create mode 100644 meta/bluesky-firehose.json create mode 100644 meta/bluesky-quote-finder.json create mode 100644 meta/bluesky-resolve.json create mode 100644 meta/bluesky-search.json create mode 100644 meta/bluesky-thread.json create mode 100644 meta/bluesky-timeline.json create mode 100644 meta/box-shadow.json create mode 100644 meta/broadcast-channel-chat.json create mode 100644 meta/bugzilla-bug.json create mode 100644 meta/bullish-bearish.json create mode 100644 meta/california-clock-change.json create mode 100644 meta/census-reporter-claude.json create mode 100644 meta/census-reporter-gemini.json create mode 100644 meta/chrome-prompt-playground.json create mode 100644 meta/claude-code-timeline.json create mode 100644 meta/claude-token-counter.json create mode 100644 meta/click-grid-to-expand.json create mode 100644 meta/clipboard-backup.json create mode 100644 meta/clipboard-viewer.json create mode 100644 meta/code-with-claude-2025.json create mode 100644 meta/codex-timeline.json create mode 100644 meta/compare-pdfs.json create mode 100644 meta/cooking-timer.json create mode 100644 meta/cors-fetch.json create mode 100644 meta/css-text-wrapping.json create mode 100644 meta/csv-marker-map.json create mode 100644 meta/date-calculator.json create mode 100644 meta/deep-research-viewer.json create mode 100644 meta/devon-lanes.json create mode 100644 meta/dot.json create mode 100644 meta/emoji-identifier.json create mode 100644 meta/encrypt.json create mode 100644 meta/escape-entities.json create mode 100644 meta/event-planner.json create mode 100644 meta/exif.json create mode 100644 meta/extract-urls.json create mode 100644 meta/ffmpeg-crop.json create mode 100644 meta/flexbox-playground.json create mode 100644 meta/footnotes-experiment.json create mode 100644 meta/gemini-bbox.json create mode 100644 meta/gemini-chat.json create mode 100644 meta/gemini-image-json.json create mode 100644 meta/gemini-mask.json create mode 100644 meta/github-account.json create mode 100644 meta/github-api-write.json create mode 100644 meta/github-graphiql.json create mode 100644 meta/github-issue-to-markdown.json create mode 100644 meta/github-ratelimit.json create mode 100644 meta/gpt-4o-audio-player.json create mode 100644 meta/grid-lanes-polyfill.json create mode 100644 meta/hacker-news-filtered.json create mode 100644 meta/hacker-news-histogram.json create mode 100644 meta/hacker-news-thread-export.json create mode 100644 meta/hn-comments-for-user.json create mode 100644 meta/html-preview.json create mode 100644 meta/huggingface-storage.json create mode 100644 meta/icon-editor.json create mode 100644 meta/iframe-api-explorer.json create mode 100644 meta/iframe-sandbox.json create mode 100644 meta/image-print.json create mode 100644 meta/image-resize-quality.json create mode 100644 meta/image-to-jpeg.json create mode 100644 meta/image-to-svg.json create mode 100644 meta/incomplete-json-printer.json create mode 100644 meta/is-it-a-bird.json create mode 100644 meta/jina-embeddings-image-token-calculator.json create mode 100644 meta/jina-reader.json create mode 100644 meta/json-diff.json create mode 100644 meta/json-schema-builder.json create mode 100644 meta/json-string-extractor.json create mode 100644 meta/json-to-markdown-transcript.json create mode 100644 meta/json-to-yaml.json create mode 100644 meta/justhtml.json create mode 100644 meta/keyboard-debug.json create mode 100644 meta/keyboard-filters.json create mode 100644 meta/lightning-timer.json create mode 100644 meta/link-extractor.json create mode 100644 meta/link-temp.json create mode 100644 meta/llm-lib.json create mode 100644 meta/markdown-math.json create mode 100644 meta/mask-visualizer.json create mode 100644 meta/mdn-timelines.json create mode 100644 meta/micropython.json create mode 100644 meta/microquickjs.json create mode 100644 meta/nav-for-headings.json create mode 100644 meta/new-yorker-style.json create mode 100644 meta/notes-to-markdown.json create mode 100644 meta/numpy-pyodide-lab.json create mode 100644 meta/ocr.json create mode 100644 meta/octave-explainer.json create mode 100644 meta/omit-needless-words.json create mode 100644 meta/open-sauce-2025.json create mode 100644 meta/openai-audio-output.json create mode 100644 meta/openai-audio.json create mode 100644 meta/openai-webrtc.json create mode 100644 meta/openfreemap-demo.json create mode 100644 meta/passkeys.json create mode 100644 meta/paste-html-subset.json create mode 100644 meta/paste-rich-text.json create mode 100644 meta/percentage-recalculator.json create mode 100644 meta/pge-outages-hmb.json create mode 100644 meta/php-deserializer.json create mode 100644 meta/pipfile.json create mode 100644 meta/pomodoro.json create mode 100644 meta/progress.json create mode 100644 meta/prompt-caching.json create mode 100644 meta/prompts-js.json create mode 100644 meta/pyodide-bar-chart.json create mode 100644 meta/pypi-changelog.json create mode 100644 meta/qr.json create mode 100644 meta/query-string-stripper.json create mode 100644 meta/quickjs.json create mode 100644 meta/reading-time.json create mode 100644 meta/render-claude-citations.json create mode 100644 meta/render-markdown.json create mode 100644 meta/rich-text-to-markdown.json create mode 100644 meta/rtf-to-html.json create mode 100644 meta/schema-dsl.json create mode 100644 meta/side-panel-dialog.json create mode 100644 meta/sloccount.json create mode 100644 meta/social-media-cropper.json create mode 100644 meta/species-observation-map.json create mode 100644 meta/speech-synthesis.json create mode 100644 meta/sql-pretty-printer.json create mode 100644 meta/sqlite-wasm.json create mode 100644 meta/svg-progressive-render.json create mode 100644 meta/svg-render.json create mode 100644 meta/svg-sandbox.json create mode 100644 meta/swagger-subset.json create mode 100644 meta/tacopy-playground.json create mode 100644 meta/terminal-to-html.json create mode 100644 meta/text-diff.json create mode 100644 meta/text-indentation.json create mode 100644 meta/text-wrap-balance-nav.json create mode 100644 meta/tiff-orientation.json create mode 100644 meta/timezones.json create mode 100644 meta/token-usage.json create mode 100644 meta/transfer-time.json create mode 100644 meta/transparent-png.json create mode 100644 meta/unix-timestamp.json create mode 100644 meta/user-agent.json create mode 100644 meta/view-pdf.json create mode 100644 meta/wikipedia-wikitext.json create mode 100644 meta/word-counter.json create mode 100644 meta/writing-style.json create mode 100644 meta/xml-validator.json create mode 100644 meta/yaml-explorer.json create mode 100644 meta/youtube-thumbnails.json create mode 100644 meta/zip-wheel-explorer.json diff --git a/build_by_month.py b/build_by_month.py index c694f97f..bf2fab3a 100644 --- a/build_by_month.py +++ b/build_by_month.py @@ -31,44 +31,19 @@ def _get_first_n_words(text: str, n: int = 15) -> str: return " ".join(words[:n]) + "..." -def _extract_summary(docs_path: Path, word_limit: int = 30) -> str: - """Extract the first paragraph of the docs file, limited to word_limit words.""" - if not docs_path.exists(): +def _extract_summary(meta_path: Path, word_limit: int = 30) -> str: + """Extract the description from the meta JSON file, limited to word_limit words.""" + if not meta_path.exists(): return "" try: - content = docs_path.read_text("utf-8").strip() - except OSError: + import json + data = json.load(meta_path.open("r", encoding="utf-8")) + description = data.get("description", "") + return _get_first_n_words(description, word_limit) + except (OSError, json.JSONDecodeError): return "" - # Remove HTML comments - if "", content) + if match: + return match.group(1) + return "" + + +def main(): + # Create meta directory if it doesn't exist + meta_dir = Path("meta") + meta_dir.mkdir(exist_ok=True) + + # Find all docs.md files in the current directory + docs_files = sorted(Path(".").glob("*.docs.md")) + + converted_count = 0 + + for docs_file in docs_files: + # Read the content + content = docs_file.read_text("utf-8") + + # Extract description and commit + description = extract_description(content) + commit = extract_commit(content) + + # Determine output filename (e.g., ai-adoption.docs.md -> meta/ai-adoption.json) + slug = docs_file.stem.replace(".docs", "") + output_file = meta_dir / f"{slug}.json" + + # Create JSON object + data = { + "description": description, + "commit": commit, + } + + # Write to file with pretty printing + output_file.write_text(json.dumps(data, indent=2) + "\n", "utf-8") + converted_count += 1 + print(f"Converted {docs_file} -> {output_file}") + + print(f"\nConverted {converted_count} files to JSON in meta/") + + +if __name__ == "__main__": + main() diff --git a/gather_links.py b/gather_links.py index f2a925cb..a30985bd 100755 --- a/gather_links.py +++ b/gather_links.py @@ -67,30 +67,17 @@ def extract_urls(text): return re.findall(url_pattern, text) -def extract_description(docs_path: Path) -> str: - """Extract the first paragraph of the generated docs markdown file.""" - if not docs_path.exists(): +def extract_description(meta_path: Path) -> str: + """Extract the description from the meta JSON file.""" + if not meta_path.exists(): return "" try: - content = docs_path.read_text("utf-8").strip() - except OSError: + data = json.load(meta_path.open("r", encoding="utf-8")) + return data.get("description", "") + except (OSError, json.JSONDecodeError): return "" - if "