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
322 changes: 161 additions & 161 deletions documents/validation/phonetic_neighbors_baseline.txt

Large diffs are not rendered by default.

111 changes: 109 additions & 2 deletions scripts/build_site.py
Original file line number Diff line number Diff line change
Expand Up @@ -3618,6 +3618,7 @@ def book_page(body, title, footer_nav="", editorial=False, contents=False):
"rabbit_heart",
"window_water",
"river_home",
"water_sprout",
}


Expand Down Expand Up @@ -3690,6 +3691,10 @@ def load_texts_editorial():
"argument_passages",
"ledger_rows",
},
"story": {
"story_blocks",
"story_passages",
},
}
if form not in form_fields:
raise ValueError(f"unknown texts editorial form: {form}")
Expand All @@ -3707,6 +3712,7 @@ def load_texts_editorial():
"refusal": "Refusal",
"original": "Original",
"essay": "Original",
"story": "Original",
}[form]
if work["method"] != expected_method:
raise ValueError(
Expand Down Expand Up @@ -3743,6 +3749,7 @@ def load_texts_editorial():
"context",
"dialogue",
"essay",
"story",
"record",
"pillars",
}
Expand Down Expand Up @@ -3772,6 +3779,7 @@ def load_texts_editorial():
"refusal": ["context", "refusal", "apparatus"],
"original": ["dialogue", "record", "record", "pillars"],
"essay": ["essay", "record", "record", "pillars"],
"story": ["story"],
}
if form in expected_kinds and major_kinds != expected_kinds[form]:
raise ValueError(
Expand Down Expand Up @@ -3882,6 +3890,34 @@ def load_texts_editorial():
raise ValueError(
f"invalid essay editorial structure: {repo_path}"
)
if form == "story":
if any(
treatment[field] != 0
for field in (
"interlinear_blocks",
"interlinear_stanzas",
"source_free_blocks",
"source_free_stanzas",
"complete_readings",
"notes",
"tables",
"pillar_sections",
)
):
raise ValueError(
f"story editorial treatment has incompatible shared counts: "
f"{repo_path}"
)
if (
not isinstance(treatment["story_blocks"], int)
or treatment["story_blocks"] < 1
or not isinstance(treatment["story_passages"], int)
or treatment["story_passages"] < treatment["story_blocks"]
or treatment["inner_dividers"] != treatment["story_blocks"] - 1
):
raise ValueError(
f"invalid story editorial structure: {repo_path}"
)
for field in (
"opening_paragraphs",
"interlinear_blocks",
Expand Down Expand Up @@ -4167,6 +4203,7 @@ def texts_motif(name):
"rabbit_heart": (rabbit, heart),
"window_water": (window, droplet),
"river_home": (waves, dwelling),
"water_sprout": (waves, sprout),
}
if name not in motifs:
raise ValueError(f"unknown texts motif: {name}")
Expand Down Expand Up @@ -4219,6 +4256,11 @@ def text_section_icon(kind):
'<path d="M20 4h-4a3 3 0 0 0-3 3v13a2 2 0 0 1 2-2h5z"/>'
'<path d="M7 9h5"/><path d="M7 13h4"/>'
),
"story": (
'<path d="M4 4h9a3 3 0 0 1 3 3v13a2 2 0 0 0-2-2H4z"/>'
'<path d="M20 4h-4a3 3 0 0 0-3 3v13a2 2 0 0 1 2-2h5z"/>'
'<path d="M7 9h5"/><path d="M7 13h4"/>'
),
"record": (
'<rect width="8" height="4" x="8" y="2" rx="1" ry="1"/>'
'<path d="M16 4h2a2 2 0 0 1 2 2v14a2 2 0 0 1-2 2H6'
Expand Down Expand Up @@ -4280,7 +4322,7 @@ def text_heading_slug(title):

def text_reading_map(treatment):
"""Build the reading map shown before a treated literary work."""
automatic_forms = {"translation", "refusal", "original", "essay"}
automatic_forms = {"translation", "refusal", "original", "essay", "story"}
if treatment["form"] in automatic_forms:
map_items = [
{
Expand Down Expand Up @@ -4529,6 +4571,67 @@ def convert(match):
return body


def style_original_story(body, repo_path, treatment):
"""Render and verify the scene passages of an original Phi story."""
block_count = 0
passage_count = 0

def convert(match):
nonlocal block_count, passage_count
raw = match.group(1).strip()
rendered = []
block_count += 1
for group in re.split(r"\n[ \t]*\n", raw):
lines = [line.strip() for line in group.splitlines()]
if (
len(lines) != 3
or not is_text_phi_passage(lines[0])
or not lines[2].startswith("(")
or not lines[2].endswith(")")
):
first_line = lines[0][:80] if lines else "(empty)"
raise ValueError(
f"unrecognized original story passage in {repo_path}: "
f"{first_line}"
)
passage_count += 1
rendered.append(
'<div class="text-story-passage" role="group" '
f'aria-label="Passage {passage_count}">'
f'<p class="text-phi-line" lang="art-x-phi">{lines[0]}</p>'
'<p class="text-gloss-line">'
'<span class="visually-hidden">Word-by-word gloss: </span>'
f"{lines[1]}</p>"
'<div class="text-story-close-reading">'
'<p class="text-literal-line">'
'<span class="visually-hidden">Close English reading: </span>'
f"{lines[2]}</p>"
"</div>"
"</div>"
)
return (
'<div class="text-story-scene" role="group" '
f'aria-label="Scene {block_count}">'
+ "".join(rendered)
+ "</div>"
)

body = re.sub(r"<pre>(.*?)</pre>", convert, body, flags=re.S)
if block_count != treatment["story_blocks"]:
raise ValueError(
f"texts editorial story block count differs in {repo_path}: "
f"expected {treatment['story_blocks']}, found {block_count}"
)
if passage_count != treatment["story_passages"]:
raise ValueError(
f"texts editorial story passage count differs in {repo_path}: "
f"expected {treatment['story_passages']}, found {passage_count}"
)
if "<pre>" in body:
raise ValueError(f"editorial text left an untreated fence in {repo_path}")
return body


def style_text_fences(body, repo_path, treatment):
"""Turn a literary work's exact fences into readings and interlinear rows."""
counts = {
Expand Down Expand Up @@ -4947,7 +5050,7 @@ def apply_text_editorial(body, source, repo_path, treatment):

opening_boundary = (
r"(?=<h2>)"
if treatment["form"] in {"original", "essay"}
if treatment["form"] in {"original", "essay", "story"}
else r"<hr>"
)
opening_pattern = re.compile(
Expand Down Expand Up @@ -5062,6 +5165,8 @@ def apply_text_editorial(body, source, repo_path, treatment):
class_name = "text-dialogue-section"
elif kind == "essay":
class_name = "text-essay-section"
elif kind == "story":
class_name = "text-story-section"
elif kind == "record":
class_name = "text-record-section"
elif kind == "pillars":
Expand All @@ -5085,6 +5190,8 @@ def apply_text_editorial(body, source, repo_path, treatment):
body = style_original_dialogue(body, repo_path, treatment)
elif treatment["form"] == "essay":
body = style_original_essay(body, repo_path, treatment)
elif treatment["form"] == "story":
body = style_original_story(body, repo_path, treatment)
else:
body = style_text_fences(body, repo_path, treatment)
body, note_count = re.subn(
Expand Down
33 changes: 32 additions & 1 deletion site/style.css
Original file line number Diff line number Diff line change
Expand Up @@ -2569,6 +2569,9 @@ a.text-certification-mark:focus-visible {
.text-original-page .text-reading-map ol {
grid-template-columns: repeat(4, minmax(0, 1fr));
}
.text-story-page .text-reading-map ol {
grid-template-columns: minmax(0, 16rem);
}
.text-rabbit-heart-page .text-reading-map ol {
gap: .55rem 1.1rem;
grid-template-columns: repeat(3, minmax(0, 1fr));
Expand Down Expand Up @@ -2611,6 +2614,7 @@ a.text-certification-mark:focus-visible {
.text-context,
.text-dialogue-section,
.text-essay-section,
.text-story-section,
.text-record-section,
.text-pillars-section { margin-top: 4rem; }
.text-editorial h2.text-method-heading {
Expand Down Expand Up @@ -2650,6 +2654,7 @@ a.text-certification-mark:focus-visible {
.text-apparatus-heading .text-section-icon { color: var(--muted); }
.text-context-heading .text-section-icon { color: var(--gold); }
.text-dialogue-heading .text-section-icon { color: var(--sage); }
.text-story-heading .text-section-icon { color: var(--sage); }
.text-record-heading .text-section-icon { color: var(--gold); }
.text-pillars-heading .text-section-icon { color: var(--sage); }
.text-section-number {
Expand Down Expand Up @@ -2861,6 +2866,24 @@ a.text-certification-mark:focus-visible {
.text-essay-passage p { margin: 0; }
.text-essay-close-reading { margin-top: .58rem; }

.text-story-scene {
border-left: 2px solid var(--sage);
margin: .8rem 0 1.5rem;
padding: .25rem 0 .25rem 1.35rem;
}
.text-story-passage {
margin: 0;
padding: .85rem 0 .92rem;
}
.text-story-passage + .text-story-passage { margin-top: .12rem; }
.text-story-passage p { margin: 0; }
.text-story-close-reading { margin-top: .58rem; }
.text-story-page .text-inner-divider {
border-top-color: var(--sage);
margin: 2.35rem 0 2.35rem 1.35rem;
width: 3.5rem;
}

.text-literal-line {
color: var(--ink);
font-family: var(--serif);
Expand Down Expand Up @@ -4616,6 +4639,9 @@ table.text-ledger {
.text-original-page .text-reading-map ol {
grid-template-columns: minmax(0, 1fr);
}
.text-story-page .text-reading-map ol {
grid-template-columns: minmax(0, 1fr);
}
.text-rabbit-heart-page .text-reading-map ol {
gap: 0 .8rem;
grid-template-columns: repeat(2, minmax(0, 1fr));
Expand Down Expand Up @@ -4827,6 +4853,10 @@ table.text-ledger {
grid-template-columns: 3.8rem minmax(0, 1fr);
}
.text-dialogue-name { font-size: .64rem; }
.text-story-scene {
margin-left: -.15rem;
padding-left: .9rem;
}
.text-ledger td,
.text-ledger td:first-child {
gap: .5rem;
Expand Down Expand Up @@ -5375,7 +5405,8 @@ table.text-ledger {
.text-notes,
.text-pillar-reflection,
.text-collection-detail,
.text-dialogue-turn { break-inside: avoid; }
.text-dialogue-turn,
.text-story-passage { break-inside: avoid; }
.text-dialogue-turn {
gap: .8em;
grid-template-columns: 4.5em minmax(0, 1fr);
Expand Down
23 changes: 23 additions & 0 deletions site/texts_editorial.json
Original file line number Diff line number Diff line change
Expand Up @@ -680,6 +680,29 @@
6,
5
]
},
"texts/a_second_way_for_water.md": {
"form": "story",
"phi_title": "phialu nu wi shoeka",
"motif": "water_sprout",
"sections": [
{
"title": "The story",
"kind": "story"
}
],
"opening_paragraphs": 2,
"interlinear_blocks": 0,
"interlinear_stanzas": 0,
"source_free_blocks": 0,
"source_free_stanzas": 0,
"complete_readings": 0,
"notes": 0,
"tables": 0,
"pillar_sections": 0,
"inner_dividers": 5,
"story_blocks": 6,
"story_passages": 96
}
}
}
1 change: 1 addition & 0 deletions texts/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ Short works each have one Markdown file. An author collection gets its own direc
| The Thing Holds Its Mending | Original | An essay on a rebuilt wall that narrows its own claim under objection and leaves the chooser of criteria open. | [Read](the_mended_wall.md) |
| When a Report Is Enough | Original | An essay on a dusk warning that justifies one chosen inspection and leaves the next walk unassigned. | [Read](the_report_at_dusk.md) |
| Worth Does Not Require a Valuer | Original | An essay on a fallen branch where a failed grammatical proof leaves a smaller claim about worth and a reason to attend. | [Read](the_worth_of_a_fallen_branch.md) |
| A Second Way for Water | Original | A pastoral story about a broken clay channel that must serve two living places, with help from one useful hoofprint. | [Read](a_second_way_for_water.md) |
| The North Wind and the Sun | Translation | The complete fable, followed by its translation limits. | [Read](north_wind_and_sun.md) |
| Article 1 of the Universal Declaration of Human Rights | Translation | Both sentences, with rights, reason, conscience, and obligation kept distinct. | [Read](human_rights_article_one.md) |
| The Babel Text | Translation | Genesis 11:1-9 in Phi translation. | [Read](babel_text.md) |
Expand Down
Loading
Loading