feat: use explicit Projects section in README

This commit is contained in:
Vinta Chen 2026-05-04 21:24:57 +08:00
parent 921d47b455
commit 6c18b6447e
No known key found for this signature in database
GPG key ID: B93DE4F003C33630
5 changed files with 190 additions and 178 deletions

View file

@ -137,31 +137,31 @@ class TestBuild:
Intro.
---
## Projects
**Tools**
## Widgets
### Widgets
_Widget libraries. Also see [awesome-widgets](https://example.com/widgets)._
- [w1](https://example.com) - A widget.
## Gadgets
### Gadgets
_Gadget tools._
- [g1](https://example.com) - A gadget.
# Resources
## Resources
Info.
## Newsletters
### Newsletters
- [NL](https://example.com)
# Contributing
## Contributing
Help!
""")
@ -179,17 +179,17 @@ class TestBuild:
Intro.
---
## Projects
**Tools**
## Widgets
### Widgets
- Sync
- [w1](https://example.com) - A widget.
# Contributing
## Contributing
Help!
""")
@ -232,7 +232,7 @@ class TestBuild:
Intro.
---
## Projects
**Tools**
@ -298,28 +298,28 @@ class TestBuild:
Intro.
# **Sponsors**
## **Sponsors**
- **[Sponsor](https://sponsor.example.com)**: Sponsored tool.
> Become a sponsor: [Sponsor us](SPONSORSHIP.md).
# Categories
## Categories
**Tools**
- [Widgets](#widgets)
---
## Projects
**Tools**
## Widgets
### Widgets
- [w1](https://example.com) - A widget.
- [w2](https://github.com/owner/w2) - A starred widget.
# Contributing
## Contributing
Help!
""")
@ -353,7 +353,7 @@ class TestBuild:
assert "## Categories" in llms_txt
assert "**Tools**" in llms_txt
assert "- [Widgets](#widgets)" in llms_txt
assert "## Widgets" in llms_txt
assert "### Widgets" in llms_txt
assert "- [w1](https://example.com) - A widget." in llms_txt
assert "- [w2](https://github.com/owner/w2) - A starred widget. (GitHub stars: 42)" in llms_txt
assert llms_txt != readme
@ -363,7 +363,7 @@ class TestBuild:
readme = textwrap.dedent("""\
# T
---
## Projects
## Only
@ -387,7 +387,7 @@ class TestBuild:
readme = textwrap.dedent("""\
# T
---
## Projects
## Stuff
@ -431,7 +431,7 @@ class TestBuild:
readme = textwrap.dedent("""\
# T
---
## Projects
**Widgets**
@ -538,7 +538,7 @@ class TestBuild:
Intro.
---
## Projects
**Tools**
@ -591,7 +591,7 @@ class TestBuild:
readme = textwrap.dedent("""\
# T
---
## Projects
**AI & ML**
@ -624,7 +624,7 @@ class TestBuild:
readme = textwrap.dedent("""\
# T
---
## Projects
**Web**
@ -659,7 +659,7 @@ class TestBuild:
readme = textwrap.dedent("""\
# T
---
## Projects
**Web**
@ -691,7 +691,7 @@ class TestBuild:
readme = textwrap.dedent("""\
# T
---
## Projects
**AI & ML**
@ -731,7 +731,7 @@ class TestBuild:
readme = textwrap.dedent("""\
# T
---
## Projects
## Sneaky </script><script>x=1</script>
@ -760,7 +760,7 @@ class TestBuild:
readme = textwrap.dedent("""\
# T
---
## Projects
**AI & ML**
@ -800,7 +800,7 @@ class TestBuild:
readme = textwrap.dedent("""\
# T
---
## Projects
**AI & ML**
@ -980,7 +980,7 @@ class TestExtractEntries:
readme = textwrap.dedent("""\
# T
---
## Projects
**Tools**
@ -1004,7 +1004,7 @@ class TestExtractEntries:
readme = textwrap.dedent("""\
# T
---
## Projects
**Tools**
@ -1031,7 +1031,7 @@ class TestExtractEntries:
readme = textwrap.dedent("""\
# T
---
## Projects
## Stdlib
@ -1050,7 +1050,7 @@ class TestExtractEntries:
readme = textwrap.dedent("""\
# T
---
## Projects
**Tools**

View file

@ -81,35 +81,35 @@ MINIMAL_README = textwrap.dedent("""\
Some intro text.
---
## Projects
## Alpha
### Alpha
_Libraries for alpha stuff._
- [lib-a](https://example.com/a) - Does A.
- [lib-b](https://example.com/b) - Does B.
## Beta
### Beta
_Tools for beta._
- [lib-c](https://example.com/c) - Does C.
# Resources
## Resources
Where to discover resources.
## Newsletters
### Newsletters
- [News One](https://example.com/n1)
- [News Two](https://example.com/n2)
## Podcasts
### Podcasts
- [Pod One](https://example.com/p1)
# Contributing
## Contributing
Please contribute!
""")
@ -120,11 +120,11 @@ GROUPED_README = textwrap.dedent("""\
Some intro text.
---
## Projects
**Group One**
## Alpha
### Alpha
_Libraries for alpha stuff._
@ -133,25 +133,25 @@ GROUPED_README = textwrap.dedent("""\
**Group Two**
## Beta
### Beta
_Tools for beta._
- [lib-c](https://example.com/c) - Does C.
## Gamma
### Gamma
- [lib-d](https://example.com/d) - Does D.
# Resources
## Resources
Where to discover resources.
## Newsletters
### Newsletters
- [News One](https://example.com/n1)
# Contributing
## Contributing
Please contribute!
""")
@ -191,7 +191,7 @@ class TestParseReadmeSections:
all_names.extend(c["name"] for c in g["categories"])
assert "Contributing" not in all_names
def test_no_separator(self):
def test_no_projects_heading(self):
groups = parse_readme("# Just a heading\n\nSome text.\n")
assert groups == []
@ -199,19 +199,19 @@ class TestParseReadmeSections:
readme = textwrap.dedent("""\
# Title
---
## Projects
## NullDesc
### NullDesc
- [item](https://x.com) - Thing.
# Resources
## Resources
## Tips
### Tips
- [tip](https://x.com)
# Contributing
## Contributing
Done.
""")
@ -225,15 +225,15 @@ class TestParseReadmeSections:
readme = textwrap.dedent("""\
# T
---
## Projects
## Algos
### Algos
_Algorithms. Also see [awesome-algos](https://example.com)._
- [lib](https://x.com) - Lib.
# Contributing
## Contributing
Done.
""")
@ -273,17 +273,17 @@ class TestParseGroupedReadme:
readme = textwrap.dedent("""\
# T
---
## Projects
**Empty**
**HasCats**
## Cat
### Cat
- [x](https://x.com) - X.
# Contributing
## Contributing
Done.
""")
@ -295,15 +295,15 @@ class TestParseGroupedReadme:
readme = textwrap.dedent("""\
# T
---
## Projects
**Note:** This is not a group marker.
## Cat
### Cat
- [x](https://x.com) - X.
# Contributing
## Contributing
Done.
""")
@ -317,19 +317,19 @@ class TestParseGroupedReadme:
readme = textwrap.dedent("""\
# T
---
## Projects
## Orphan
### Orphan
- [x](https://x.com) - X.
**A Group**
## Grouped
### Grouped
- [y](https://x.com) - Y.
# Contributing
## Contributing
Done.
""")
@ -405,15 +405,15 @@ class TestParseSectionEntries:
readme = textwrap.dedent("""\
# T
---
## Projects
## Async
### Async
- [asyncio](https://x.com) - Async I/O.
- [awesome-asyncio](https://y.com)
- [trio](https://z.com) - Friendly async.
# Contributing
## Contributing
Done.
""")
@ -480,21 +480,21 @@ class TestParseRealReadme:
md = MarkdownIt("commonmark")
root = SyntaxTreeNode(md.parse(self.readme_text))
# Find category section boundaries (between --- and # Resources/Contributing)
hr_idx = None
# Find category section boundaries (between Projects and Resources/Contributing)
projects_idx = None
end_idx = None
for i, node in enumerate(root.children):
if hr_idx is None and node.type == "hr":
hr_idx = i
elif node.type == "heading" and node.tag == "h1":
if node.type == "heading" and node.tag in ("h1", "h2"):
text = render_inline_text(node.children[0].children) if node.children else ""
if end_idx is None and text in ("Resources", "Contributing"):
if projects_idx is None and text == "Projects":
projects_idx = i
elif end_idx is None and text in ("Resources", "Contributing"):
end_idx = i
if hr_idx is None:
if projects_idx is None:
return
bad = []
cat_nodes = root.children[hr_idx + 1 : end_idx or len(root.children)]
cat_nodes = root.children[projects_idx + 1 : end_idx or len(root.children)]
for node in cat_nodes:
if node.type != "bullet_list":
continue