A note's name is one rule, pinned by the shared fixture

The server and the core each derived display_title and disagreed twice: the
server cut it at 200 characters and the core didn't, and the server split lines
with splitlines(), which also breaks on a lone \r or a U+2028, where the core and
every other reading of the grammar split on \n alone.

- grammar.json gains a display_titles section: blank lines, markers, an empty
  item, \r\n, a lone \r, U+2028, and a 201-character line of 'é' (the cut is
  characters, not bytes).
- derive::display_title and DISPLAY_TITLE_CAP are the core's half, moved next to
  strip_marker. The server splits on "\n". Both suites run the cases.

Behaviour: a device now names a note with a first line over 200 characters the
way the web always has, and the server names a note containing a lone \r or a
U+2028 the way devices always have.

Fixes #5398. DRY pass #2, batch 3 (#5372).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
2026-10-08 14:27:32 -04:00
co-authored by Claude Opus 5.5
parent 2809c26214
commit db9e9a2dfb
5 changed files with 63 additions and 27 deletions
+6
View File
@@ -13,6 +13,7 @@ from pathlib import Path
import pytest
from inkwell.notes.checklist import parse_items, render_item
from inkwell.notes.helpers import derive_display_title
from inkwell.notes.tags import parse_tags, split_body_tags
FIXTURE = json.loads(
@@ -41,3 +42,8 @@ def test_tags(case):
def test_lifts(case):
standalone, inline, lifted = split_body_tags(case["body"])
assert (standalone, inline, lifted) == (case["standalone"], case["inline"], case["lifted"])
@pytest.mark.parametrize("case", FIXTURE["display_titles"], ids=lambda c: repr(c["body"][:40]))
def test_display_titles(case):
assert derive_display_title(case["body"]) == case["title"]