20 Commits

Author SHA1 Message Date
Vinta Chen 6c18b6447e feat: use explicit Projects section in README 2026-05-04 21:24:57 +08:00
Vinta Chen 3d99f7336d style(website): apply ruff format
Co-Authored-By: Claude <noreply@anthropic.com>
2026-05-03 12:23:55 +08:00
Vinta Chen b00395a301 add missing links of category descriptions 2026-05-02 23:35:24 +08:00
Vinta Chen 92936964b6 refactor(readme_parser): fuse _parse_sponsor_item into single pass
Eliminate the redundant _find_link_deep precheck by merging the two
walks over inline.children into one loop that simultaneously locates
the link and records its top-level index.

Co-Authored-By: Claude <noreply@anthropic.com>
2026-04-19 22:06:41 +08:00
Vinta Chen 420bf8cd9d refactor(readme_parser): collapse render_inline_html/text into _render_inline helper
Merge the two inline-renderer implementations into a single _render_inline(children, *, html) function that handles both output modes. The original public functions become one-line wrappers so all dispatch logic lives in one place. Also aligns html_inline handling: the html=True path now escapes the raw content instead of silently dropping it in the plain-text path.

Co-Authored-By: Claude <noreply@anthropic.com>
2026-04-19 22:05:35 +08:00
Vinta Chen 85b55efb28 refactor(readme_parser): inline _is_leading_link at its call site
The helper was only called once and the bool(inline.children) guard
was redundant: first_link being non-None already implies inline.children
is non-empty.

Co-Authored-By: Claude <noreply@anthropic.com>
2026-04-19 21:59:59 +08:00
Vinta Chen 486fbf2185 refactor(readme_parser): replace _find_first_link with _find_child(inline, "link")
The private helper duplicated _find_child with a hardcoded type filter.
Remove it and call the general helper directly at both call sites.

Co-Authored-By: Claude <noreply@anthropic.com>
2026-04-19 21:59:16 +08:00
Vinta Chen e0b0dc9c0a refactor(readme_parser): add _href helper to narrow attrGet return type
Extracts a _href(link) helper that returns link.attrGet('href') narrowed
to str (falling back to '') instead of the raw str|int|float|None union.
Replaces all four attrGet('href') or '' call sites with _href(), fixing
ty errors where the widened union leaked into TypedDict url fields.

Co-Authored-By: Claude <noreply@anthropic.com>
2026-04-19 21:58:27 +08:00
Vinta Chen e47d229528 refactor(readme_parser): consolidate state reset to tail of flush_group
State reset (current_group_name = None, current_group_cats = []) was
duplicated in both branches of the early-return guard. Move it after
the conditional so it runs exactly once regardless of path.

Co-Authored-By: Claude <noreply@anthropic.com>
2026-04-19 21:54:16 +08:00
Vinta Chen 774ab69bcd feat(website): add sponsors section parsed from README
Parse the # Sponsors heading in README.md into structured data and
render a dedicated sponsor band above the library index on the site.

Co-Authored-By: Claude <noreply@anthropic.com>
2026-04-19 21:10:50 +08:00
Vinta Chen 25a3f4d903 refactor(parser): remove resources parsing, preview, and content_html fields
parse_readme now returns list[ParsedGroup] instead of a tuple. The
resources section (Newsletters, Podcasts), preview string, and
content_html rendering are no longer produced by the parser or consumed
by the build. Removes _render_section_html, _group_by_h2, and the
associated dead code and tests.

Co-Authored-By: Claude <noreply@anthropic.com>
2026-03-23 01:43:19 +08:00
Vinta Chen e1a88410d3 fix(parser): strip trailing separators and links from subcategory labels
Type Checkers heading now reads 'Type Checkers - [awesome-python-typing](...)'
where a link follows the separator. The old code passed all inline children to
render_inline_text, which included the link URL in the label. Now we take only
the text nodes before the first link and strip trailing punctuation/separators
so the rendered subcategory label is clean.

Co-Authored-By: Claude <noreply@anthropic.com>
2026-03-23 01:19:05 +08:00
Vinta Chen f2b4a7bc83 feat(website): surface subcategory labels as filterable tags
Entries nested under a plain-text subcategory heading (e.g. "Frameworks"
inside Testing) now carry a subcategory field populated by the parser.
The build pipeline collects these into a subcategories list on each merged
entry, and the template renders them as tag-subcat buttons that plug into
the existing data-cats filter mechanism.

A dedicated .tag-subcat style distinguishes them visually from category
tags, and both are hidden on mobile alongside .tag-group.

Co-Authored-By: Claude <noreply@anthropic.com>
2026-03-23 01:04:20 +08:00
Vinta Chen 4322026817 refactor: parse thematic groups from README bold markers instead of hardcoding them
The website builder previously relied on a hardcoded SECTION_GROUPS list in
build.py to organize categories into thematic groups. This was fragile: any
rename or addition to README.md required a matching code change.

Replace this with a parser-driven approach:
- readme_parser.py now detects bold-only paragraphs (**Group Name**) as
  group boundary markers and groups H2 categories beneath them into
  ParsedGroup structs.
- build.py drops SECTION_GROUPS entirely; group_categories() now just
  passes parsed groups through and appends the Resources group.
- sort.py is removed as it relied on the old flat section model.
- Tests updated throughout to reflect the new (groups, resources) return
  shape and to cover the new grouping logic.

Co-Authored-By: Claude <noreply@anthropic.com>
2026-03-20 18:43:09 +08:00
Vinta Chen 280f250ce0 feat: migrate README parser to markdown-it-py and refresh website
Switch readme_parser.py from regex-based parsing to markdown-it-py for
more robust and maintainable Markdown AST traversal. Update build pipeline,
templates, styles, and JS to support the new parser output. Refresh GitHub
stars data and update tests to match new parser behavior.

Co-Authored-By: Claude <noreply@anthropic.com>
2026-03-18 20:33:36 +08:00
Vinta Chen 266a6b6b6c simplify: remove redundant _has_description, unused param, merge loops
- Remove `_has_description` which duplicated `_extract_description` logic;
  use truthiness of the description string instead
- Remove unused `resources` parameter from `extract_entries`
- Merge two sequential loops in `parse_readme` into a single pass over
  children to find hr, Resources, and Contributing indices

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-18 17:41:13 +08:00
Vinta Chen a83809886c feat: implement HTML rendering for readme sections
Replace the _render_section_html stub with a working implementation that
converts parsed bullet-list nodes into classed div elements (entry,
entry-sub, subcat). Add _render_bullet_list_html to handle nested
structure and XSS escaping. Cover all cases with a new
TestRenderSectionHtml suite.

Co-Authored-By: Claude <noreply@anthropic.com>
2026-03-18 17:24:24 +08:00
Vinta Chen 3d015bc630 feat(parser): implement entry extraction from bullet list AST nodes
Replace _parse_section_entries stub with full implementation that walks
bullet_list AST nodes to extract ParsedEntry records, including support
for subcategory labels (text-only list items) and also_see nested links.

Add _parse_list_entries, helper finders (_find_inline, _find_first_link,
_find_child), and _extract_description_html with separator stripping.

Extend test suite with TestParseSectionEntries covering flat entries,
link-only entries, subcategorized entries, also_see, entry_count, preview
first-four, and XSS escaping in description HTML.

Co-Authored-By: Claude <noreply@anthropic.com>
2026-03-18 17:23:11 +08:00
Vinta Chen 1c67c9f0e6 feat: replace regex README parser with markdown-it-py AST parser
Introduce parse_readme() which uses MarkdownIt to build a full AST
instead of line-by-line regex matching. The function splits the document
at the thematic break, groups nodes by h2 heading, extracts category
descriptions from leading italic paragraphs, and separates the
Categories, Resources, and Contributing sections cleanly.

Add markdown-it-py==4.0.0 (+ mdurl) as a runtime dependency to support
the new parser.

Tests cover section counts, names, slugs, descriptions, content
presence, boundary conditions (no separator, no description), and mixed
description markup.

Co-Authored-By: Claude <noreply@anthropic.com>
2026-03-18 17:21:49 +08:00
Vinta Chen 5fa7c7d1a6 feat(website): add markdown-it-py README parser and inline renderer tests
Introduce readme_parser.py which parses README.md into structured
section data using the markdown-it-py AST. Includes TypedDicts for
ParsedEntry/ParsedSection, slugify(), render_inline_html(), and
render_inline_text(). Add test_readme_parser.py covering HTML escaping,
link rendering, emphasis, strong, and code_inline for both renderers.

Co-Authored-By: Claude <noreply@anthropic.com>
2026-03-18 17:20:23 +08:00