Sort the story list without a leading The, A or An

This commit is contained in:
tim
2026-09-27 23:38:28 +02:00
parent df9959a078
commit ee611cd283
2 changed files with 19 additions and 2 deletions
+11 -2
View File
@@ -6,6 +6,7 @@ site without losing text.
"""
import json
import re
import sqlite3
from collections.abc import Iterator
from contextlib import contextmanager
@@ -120,6 +121,14 @@ def _story(row: sqlite3.Row | None) -> dict[str, Any] | None:
return d
_ARTICLE = re.compile(r"^(?:the|an?)\s+", re.I)
def sort_title(title: str | None) -> str:
"""The key that sorts a story list by title, without a leading "The", "A" or "An"."""
return _ARTICLE.sub("", (title or "").strip()).casefold()
class Store:
def __init__(self, path: Path) -> None:
self.path = Path(path)
@@ -190,8 +199,8 @@ class Store:
AND c.on_site = 0) AS offsite_count,
(SELECT COUNT(*) FROM chapters c WHERE c.story_id = s.id AND c.included = 1
AND (SELECT COUNT(*) FROM revisions r WHERE r.chapter_id = c.id) > 1) AS revised_count
FROM stories s ORDER BY s.title COLLATE NOCASE""").fetchall()
return [_story(r) for r in rows]
FROM stories s""").fetchall()
return [_story(r) for r in sorted(rows, key=lambda r: sort_title(r["title"]))]
def update_story(self, story_id: int, **fields: Any) -> None:
if not fields:
+8
View File
@@ -47,6 +47,14 @@ def test_list_stories_counts_offsite_and_revised_chapters(tmp_path):
assert story["revised_count"] == 1
def test_list_stories_sorts_titles_without_leading_articles(tmp_path):
store = Store(tmp_path / "db.sqlite")
for n, title in enumerate(["The Zebra", "an Owl", "Anthem", "A Bee", "Theory", "Cat"]):
store.create_story(f"https://example/s/{n}", "example", title, "A", [])
titles = [s["title"] for s in store.list_stories()]
assert titles == ["Anthem", "A Bee", "Cat", "an Owl", "Theory", "The Zebra"]
def test_cover_replaces_previous_cover(tmp_path):
store = Store(tmp_path / "db.sqlite")
sid = store.create_story("u", "s", "T", "A", [])