Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions .github/actions/prose-gate/prose_lint.py
Original file line number Diff line number Diff line change
Expand Up @@ -2371,8 +2371,9 @@ def check_file(path: Path, rules: set[str], root: Path | None = None) -> list[tu
# Both prose rules are Markdown-only until a comment can be told from code.
# A shell script carries 78 statement separators that are not prose at all.
if path.suffix == ".md":
unquoted = QUOTE_PREFIX.sub(lambda m: " " * len(m.group()), prose, count=1)
if "semicolon" in rules:
for span in list_spans(prose):
for span in list_spans(unquoted):
# The sentence is the unit, since the list an exemption protects lives in one.
# Judged over a whole bullet, one colon exempted every semicolon after it.
for sentence in sentences(span):
Expand All @@ -2388,7 +2389,6 @@ def check_file(path: Path, rules: set[str], root: Path | None = None) -> list[tu
(i, "semicolon", "semicolon in prose -> a comma or two sentences")
)
if "dash" in rules:
unquoted = QUOTE_PREFIX.sub(lambda m: " " * len(m.group()), prose, count=1)
skip = LABEL_DASH.match(unquoted)
for m in DASH.finditer(unquoted):
if skip and m.start() < skip.end():
Expand Down
30 changes: 30 additions & 0 deletions tests/test_prose_lint.py
Original file line number Diff line number Diff line change
Expand Up @@ -519,6 +519,36 @@ def test_a_bullet_label_colon_inside_the_emphasis_is_the_same_opener(self) -> No
),
)

def test_a_blockquoted_bullet_label_colon_does_not_announce_a_list(self) -> None:
"""A callout's `>` is structure, so its bullet is judged as the same bullet unquoted."""
for text in (
"- **Label**: one, two; three\n",
"> - **Label**: one, two; three\n",
">- **Label**: one, two; three\n",
"> > - **Label**: one, two; three\n",
"> 1. **Label:** one, two; three\n",
):
with self.subTest(text=text.strip()):
self.assertEqual(["semicolon"], self.kinds(text, {"semicolon"}))

def test_a_blockquoted_line_keeps_the_exemptions_it_has_unquoted(self) -> None:
"""Only the prefix is blanked, so a list in a callout keeps its semicolons."""
self.assertEqual(
[], self.kinds("> Inputs: a, b, and c; outputs: d and e.\n", {"semicolon"})
)

def test_a_blockquoted_table_row_judges_each_cell_alone(self) -> None:
"""A row inside a callout is still a record of fields rather than one sentence.

Read whole, the first cell's colon and the last cell's comma made the row a list.
"""
for text in (
"| S1: x | it runs; it gates | D1, D2 |\n",
"> | S1: x | it runs; it gates | D1, D2 |\n",
):
with self.subTest(text=text.strip()):
self.assertEqual(["semicolon"], self.kinds(text, {"semicolon"}))

def test_an_abbreviation_does_not_end_a_sentence(self) -> None:
"""Splitting at `e.g.` cuts a list in half and flags the separator the exemption protects."""
self.assertEqual(
Expand Down
Loading