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:
Vendored
+14
-1
@@ -1,9 +1,10 @@
|
||||
{
|
||||
"_about": [
|
||||
"The cases every implementation of the note grammar is tested against.",
|
||||
"One file, read by four test suites: core (derive.rs), the server (checklist.py, tags.py), the web (markdown.ts, colors.ts) and, for the tint, Android (DerivedTint.kt, which pins the same values by hand).",
|
||||
"One file, read by four test suites: core (derive.rs), the server (checklist.py, tags.py, helpers.py), the web (markdown.ts, colors.ts) and, for the tint, Android (DerivedTint.kt, which pins the same values by hand).",
|
||||
"A difference between any two implementations is a note that changes shape when it syncs. Add a case here, not to one suite.",
|
||||
"Lives under core/ because core is the definition, and because core/ is in the desktop, Android and server file sets, so changing a case reruns every suite that reads it.",
|
||||
"display_titles: a note's name is its first line that says anything once a task marker is stripped, cut to 200 characters (not bytes). Lines split on \\n alone, as the grammar does everywhere.",
|
||||
"Tag cases are plain text on purpose. The web's renderer lets `code` and **bold** claim a `#` first, which the derivers do not; that is a rendering choice, not grammar, and is tested where it lives."
|
||||
],
|
||||
|
||||
@@ -68,6 +69,18 @@
|
||||
{ "body": "(#todo)\nnotes", "standalone": [], "inline": [], "lifted": "(#todo)\nnotes" }
|
||||
],
|
||||
|
||||
"display_titles": [
|
||||
{ "body": "", "title": "" },
|
||||
{ "body": "\n\n Shopping \nmilk", "title": "Shopping" },
|
||||
{ "body": "- [ ] milk\n- [x] eggs", "title": "milk" },
|
||||
{ "body": "- [ ]\n- [ ] bread", "title": "bread" },
|
||||
{ "body": " \n\t\nlate start", "title": "late start" },
|
||||
{ "body": "one\r\ntwo", "title": "one" },
|
||||
{ "body": "a\rb\nc", "title": "a\rb" },
|
||||
{ "body": "a\u2028b\nc", "title": "a\u2028b" },
|
||||
{ "body": "ééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééé", "title": "éééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééé" }
|
||||
],
|
||||
|
||||
"tint": {
|
||||
"keys": ["red", "orange", "yellow", "green", "teal", "blue", "purple", "pink", "gray"],
|
||||
"hashes": [
|
||||
|
||||
Reference in New Issue
Block a user