calliope-ts 0.0.1 → 0.0.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +101 -205
- package/dist/caesura.d.ts +33 -0
- package/dist/caesura.d.ts.map +1 -0
- package/dist/caesura.js +202 -0
- package/dist/calliope/boundaries.d.ts +19 -0
- package/dist/calliope/boundaries.d.ts.map +1 -0
- package/dist/calliope/boundaries.js +182 -0
- package/dist/calliope/bracketing.d.ts +11 -0
- package/dist/calliope/bracketing.d.ts.map +1 -0
- package/dist/calliope/bracketing.js +416 -0
- package/dist/calliope/deps.d.ts +4 -0
- package/dist/calliope/deps.d.ts.map +1 -0
- package/dist/calliope/deps.js +181 -0
- package/dist/calliope/engine.d.ts +3 -0
- package/dist/calliope/engine.d.ts.map +1 -0
- package/dist/calliope/engine.js +71 -0
- package/dist/calliope/feats.d.ts +9 -0
- package/dist/calliope/feats.d.ts.map +1 -0
- package/dist/calliope/feats.js +45 -0
- package/dist/calliope/names.d.ts +7 -0
- package/dist/calliope/names.d.ts.map +1 -0
- package/dist/calliope/names.js +42 -0
- package/dist/calliope/postag.d.ts +8 -0
- package/dist/calliope/postag.d.ts.map +1 -0
- package/dist/calliope/postag.js +250 -0
- package/dist/calliope/prosodic.d.ts +3 -0
- package/dist/calliope/prosodic.d.ts.map +1 -0
- package/dist/calliope/prosodic.js +275 -0
- package/dist/calliope/relstress.d.ts +4 -0
- package/dist/calliope/relstress.d.ts.map +1 -0
- package/dist/calliope/relstress.js +688 -0
- package/dist/calliope/stressrules.d.ts +28 -0
- package/dist/calliope/stressrules.d.ts.map +1 -0
- package/dist/calliope/stressrules.js +147 -0
- package/dist/calliope/syntax.d.ts +38 -0
- package/dist/calliope/syntax.d.ts.map +1 -0
- package/dist/calliope/syntax.js +234 -0
- package/dist/calliope/udpos.d.ts +13 -0
- package/dist/calliope/udpos.d.ts.map +1 -0
- package/dist/calliope/udpos.js +156 -0
- package/dist/clio/caesura.d.ts +27 -0
- package/dist/clio/caesura.d.ts.map +1 -0
- package/dist/clio/caesura.js +148 -0
- package/dist/clio/depfix.d.ts +13 -0
- package/dist/clio/depfix.d.ts.map +1 -0
- package/dist/clio/depfix.js +84 -0
- package/dist/clio/display.d.ts +32 -0
- package/dist/clio/display.d.ts.map +1 -0
- package/dist/clio/display.js +976 -0
- package/dist/clio/engine.d.ts +3 -0
- package/dist/clio/engine.d.ts.map +1 -0
- package/dist/clio/engine.js +28 -0
- package/dist/clio/parser.d.ts +10 -0
- package/dist/clio/parser.d.ts.map +1 -0
- package/dist/clio/parser.js +696 -0
- package/dist/clio/phonological.d.ts +41 -0
- package/dist/clio/phonological.d.ts.map +1 -0
- package/dist/clio/phonological.js +788 -0
- package/dist/clio/phrasestress.d.ts +6 -0
- package/dist/clio/phrasestress.d.ts.map +1 -0
- package/dist/clio/phrasestress.js +106 -0
- package/dist/clio/pipeline.d.ts +11 -0
- package/dist/clio/pipeline.d.ts.map +1 -0
- package/dist/clio/pipeline.js +147 -0
- package/dist/clio/rhyme.d.ts +65 -0
- package/dist/clio/rhyme.d.ts.map +1 -0
- package/dist/clio/rhyme.js +761 -0
- package/dist/clio/scandroid.d.ts +17 -0
- package/dist/clio/scandroid.d.ts.map +1 -0
- package/dist/clio/scandroid.js +435 -0
- package/dist/clio/scansion.d.ts +46 -0
- package/dist/clio/scansion.d.ts.map +1 -0
- package/dist/clio/scansion.js +1086 -0
- package/dist/clio/semantics.d.ts +44 -0
- package/dist/clio/semantics.d.ts.map +1 -0
- package/dist/clio/semantics.js +139 -0
- package/dist/clio/stress.d.ts +83 -0
- package/dist/clio/stress.d.ts.map +1 -0
- package/dist/clio/stress.js +1737 -0
- package/dist/clio/tagfix.d.ts +6 -0
- package/dist/clio/tagfix.d.ts.map +1 -0
- package/dist/clio/tagfix.js +101 -0
- package/dist/display.d.ts +0 -6
- package/dist/display.d.ts.map +1 -1
- package/dist/display.js +322 -141
- package/dist/engine.d.ts +9 -0
- package/dist/engine.d.ts.map +1 -0
- package/dist/engine.js +12 -0
- package/dist/index.d.ts +4 -3
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +178 -27
- package/dist/parser.d.ts +3 -3
- package/dist/parser.d.ts.map +1 -1
- package/dist/parser.js +320 -563
- package/dist/phonological.d.ts +1 -1
- package/dist/phonological.d.ts.map +1 -1
- package/dist/phonological.js +73 -4
- package/dist/phrasestress.d.ts +6 -0
- package/dist/phrasestress.d.ts.map +1 -0
- package/dist/phrasestress.js +106 -0
- package/dist/rhyme.d.ts +40 -1
- package/dist/rhyme.d.ts.map +1 -1
- package/dist/rhyme.js +435 -7
- package/dist/scansion.d.ts +9 -0
- package/dist/scansion.d.ts.map +1 -1
- package/dist/scansion.js +145 -18
- package/dist/semantics.d.ts +44 -0
- package/dist/semantics.d.ts.map +1 -0
- package/dist/semantics.js +139 -0
- package/dist/stress.d.ts +127 -4
- package/dist/stress.d.ts.map +1 -1
- package/dist/stress.js +834 -61
- package/dist/types.d.ts +15 -0
- package/dist/types.d.ts.map +1 -1
- package/package.json +5 -3
- package/src/caesura.ts +201 -0
- package/src/calliope/boundaries.ts +190 -0
- package/src/calliope/bracketing.ts +390 -0
- package/src/calliope/deps.ts +160 -0
- package/src/calliope/engine.ts +77 -0
- package/src/calliope/feats.ts +46 -0
- package/src/calliope/names.ts +44 -0
- package/src/calliope/postag.ts +253 -0
- package/src/calliope/prosodic.ts +262 -0
- package/src/calliope/relstress.ts +645 -0
- package/src/calliope/stressrules.ts +147 -0
- package/src/calliope/syntax.ts +218 -0
- package/src/calliope/udpos.ts +152 -0
- package/src/clio/caesura.ts +145 -0
- package/src/clio/depfix.ts +88 -0
- package/src/clio/display.ts +1042 -0
- package/src/clio/engine.ts +38 -0
- package/src/clio/parser.ts +845 -0
- package/src/clio/phonological.ts +849 -0
- package/src/clio/phrasestress.ts +108 -0
- package/src/clio/pipeline.ts +154 -0
- package/src/clio/rhyme.ts +740 -0
- package/src/clio/scandroid.ts +434 -0
- package/src/clio/scansion.ts +1130 -0
- package/src/clio/semantics.ts +134 -0
- package/src/clio/stress.ts +1731 -0
- package/src/clio/tagfix.ts +104 -0
- package/src/display.ts +321 -137
- package/src/engine.ts +22 -0
- package/src/index.ts +180 -31
- package/src/parser.ts +346 -682
- package/src/phonological.ts +72 -4
- package/src/phrasestress.ts +108 -0
- package/src/rhyme.ts +428 -8
- package/src/scansion.ts +136 -15
- package/src/semantics.ts +134 -0
- package/src/stress.ts +794 -64
- package/src/types.ts +39 -4
- package/tests/DataForHayesLinesOnly.txt +364 -0
- package/tests/DataForHayesStressSymbolsRevised.txt +728 -0
- package/tests/basic.test.ts +1102 -0
- package/tests/bench-hayes.mjs +72 -0
- package/tests/epg64.meter.train.txt +8139 -0
- package/tests/litlab-sample-2016.txt +1738 -0
- package/tests/prosodic.meter.train.txt +13192 -0
- package/tests/wagner-stress.test.ts +188 -0
- package/tsconfig.json +29 -0
- package/vitest.config.d.ts +2 -0
- package/vitest.config.js +14 -0
- package/.claude/settings.local.json +0 -8
- package/.opencode/skills/calliope-ts/SKILL.md +0 -74
package/README.md
CHANGED
|
@@ -1,31 +1,21 @@
|
|
|
1
1
|
# Calliope TS
|
|
2
2
|
|
|
3
|
-
**Calliope TS** is a phonological poetry-scansion toolkit for TypeScript / Node.js.
|
|
4
|
-
|
|
5
|
-
you
|
|
6
|
-
metrical beats fall, what meter each line is written in, how certain that
|
|
7
|
-
reading is, what the rhyme scheme is, and what poetic form the stanzas add up
|
|
8
|
-
to.
|
|
9
|
-
|
|
10
|
-
It is not a syllable-counter with a rulebook bolted on. Calliope TS scans verse
|
|
11
|
-
the way a trained reader does: it first works out how the words would actually
|
|
12
|
-
be *spoken* — dictionary stress, phrase rhythm, sentence intonation — and only
|
|
13
|
-
then asks which metrical pattern that spoken contour fits best.
|
|
3
|
+
**Calliope TS** is a phonological poetry-scansion toolkit for TypeScript / Node.js. Hand it a poem (or a single line), and it will tell you — and *show* you — how that verse actually moves: which syllables carry weight and how much, where the beats fall, what meter each line is in and how confidently, what rhymes with what, and what form the stanzas add up to.
|
|
4
|
+
|
|
5
|
+
The premise is that meter is something you *recover from pronunciation*, not something you stamp onto spelling. So Calliope reads a line roughly the way an attentive reader does: it first works out how the words would be said aloud — dictionary stress, the way phrases clump, where the voice peaks at a clause-end — and only then looks for the regular beat that saying settles into. This approach has a name in the linguistics literature, **phonological scansion**, and the bulk of this README is about what that means and how the toolkit puts it to work.
|
|
14
6
|
|
|
15
7
|
```
|
|
16
8
|
$ calliope-ts --reading exile.txt
|
|
17
9
|
|
|
18
10
|
Reading View — stress gradient over the original text
|
|
19
11
|
|
|
20
|
-
He happens to be a French poet, that thin,
|
|
21
|
-
book-carrying man with a bristly gray chin;
|
|
12
|
+
He happens to be a French poet, that thin, ← each syllable is tinted by how
|
|
13
|
+
book-carrying man with a bristly gray chin; much stress it carries (see below)
|
|
22
14
|
...
|
|
23
15
|
|
|
24
|
-
Stress Maps & Meter — top-3
|
|
25
|
-
S1L1 nsw|xwx|msw ‖ xs amphibrachic tetrameter (amph 1.20 · iamb 1.14 ·
|
|
26
|
-
|
|
27
|
-
S1L2 m|-mww|sxx|mwm|s amphibrachic tetrameter ≈ continuity; standalone:
|
|
28
|
-
dactylic tetrameter A(perfect)
|
|
16
|
+
Stress Maps & Meter — top-3 candidate meters per line
|
|
17
|
+
S1L1 nsw|xwx|msw ‖ xs amphibrachic tetrameter (amph 1.20 · iamb 1.14 · anap 1.13) A
|
|
18
|
+
S1L2 m-mw|wsx|xmw|ms amphibrachic tetrameter ≈ continuity; standalone: dactylic tetrameter A
|
|
29
19
|
...
|
|
30
20
|
```
|
|
31
21
|
|
|
@@ -36,9 +26,12 @@ Stress Maps & Meter — top-3 fit scores per line
|
|
|
36
26
|
- [Installation](#installation)
|
|
37
27
|
- [Quick start (CLI)](#quick-start-cli)
|
|
38
28
|
- [Reading the output](#reading-the-output)
|
|
39
|
-
- [
|
|
29
|
+
- [What "phonological scansion" means](#what-phonological-scansion-means)
|
|
30
|
+
- [The pipeline, stage by stage](#the-pipeline-stage-by-stage)
|
|
31
|
+
- [A note on rules vs. constraints](#a-note-on-rules-vs-constraints)
|
|
40
32
|
- [Programmatic usage (API)](#programmatic-usage-api)
|
|
41
33
|
- [Examples](#examples)
|
|
34
|
+
- [How it compares to other scanners](#how-it-compares-to-other-scanners)
|
|
42
35
|
- [Background and lineage](#background-and-lineage)
|
|
43
36
|
- [Scope, strengths, and honest limitations](#scope-strengths-and-honest-limitations)
|
|
44
37
|
- [Development](#development)
|
|
@@ -48,15 +41,13 @@ Stress Maps & Meter — top-3 fit scores per line
|
|
|
48
41
|
|
|
49
42
|
## Installation
|
|
50
43
|
|
|
51
|
-
Requires **Node.js ≥ 20** (≥ 22 recommended — one optional
|
|
52
|
-
dependency-tree repair, needs Node's `require(esm)` support and degrades
|
|
53
|
-
gracefully without it).
|
|
44
|
+
Requires **Node.js ≥ 20** (≥ 22 recommended — one optional stage, the dependency-tree repair, uses Node's `require(esm)` support and simply switches itself off on older runtimes).
|
|
54
45
|
|
|
55
46
|
```bash
|
|
56
47
|
# As a global CLI tool
|
|
57
48
|
npm install -g calliope-ts
|
|
58
49
|
|
|
59
|
-
# Or as a library
|
|
50
|
+
# Or as a library inside your own project
|
|
60
51
|
npm install calliope-ts
|
|
61
52
|
```
|
|
62
53
|
|
|
@@ -79,14 +70,14 @@ calliope-ts "Shall I compare thee to a summer's day?"
|
|
|
79
70
|
# 2. Scan a whole poem from a file (blank lines separate stanzas)
|
|
80
71
|
calliope-ts poem.txt
|
|
81
72
|
|
|
82
|
-
# 3.
|
|
83
|
-
#
|
|
84
|
-
|
|
73
|
+
# 3. Reading view — the poem itself, syllables tinted by stress
|
|
74
|
+
# (the nicest way to read a whole poem; first option in the CLI;
|
|
75
|
+
or add -r or --reading)
|
|
85
76
|
|
|
86
77
|
# 4. Pipe text in
|
|
87
78
|
cat poem.txt | calliope-ts --reading
|
|
88
79
|
|
|
89
|
-
# 5. Interactive menu (run
|
|
80
|
+
# 5. Interactive menu (run without typing arguments in a terminal each time)
|
|
90
81
|
calliope-ts
|
|
91
82
|
```
|
|
92
83
|
|
|
@@ -119,31 +110,34 @@ core representation everything else is built on):
|
|
|
119
110
|
| `s` | strong | primary stresses, phrase peaks, line-final nuclei |
|
|
120
111
|
|
|
121
112
|
A line's **stress map** is simply its syllables in order, e.g.
|
|
122
|
-
`xs|wxm|wxs|xws` — with
|
|
123
|
-
|
|
124
|
-
|
|
113
|
+
`xs|wxm|wxs|xws` — with:
|
|
114
|
+
`|` marking foot boundaries;
|
|
115
|
+
`‖` a strong caesura (aka syntactic pause) at major phonological/clausal or punctuation breaks;
|
|
116
|
+
`¦` a lighter phrase break;
|
|
117
|
+
`-` a "silent beat" inserted to neutralize a stress clash wherever two strongly-stressed syllables would otherwise collide, it forces the second to await its turn.
|
|
125
118
|
|
|
126
119
|
### Meter lines
|
|
127
120
|
|
|
121
|
+
In the reading view each verse-line gets a single summary line.
|
|
122
|
+
Reading one such line left to right:
|
|
123
|
+
|
|
128
124
|
```
|
|
129
125
|
S1L2 m|-mww|sxx|mwm|s amphibrachic tetrameter (dact 1.21 · amph 1.17 ·
|
|
130
126
|
anap 1.16) ≈ continuity; standalone: dactylic tetrameter A(perfect)
|
|
131
127
|
```
|
|
132
128
|
|
|
133
|
-
- **`amphibrachic tetrameter`** — the line's meter: foot type +
|
|
129
|
+
- **`amphibrachic tetrameter`** — the line's meter: foot type + count.
|
|
134
130
|
- **`(dact 1.21 · amph 1.17 · anap 1.16)`** — the top three candidate meters
|
|
135
131
|
with their raw fit scores. The named meter need not be the numerically
|
|
136
132
|
first candidate: ties between sibling meters are resolved by principled
|
|
137
133
|
criteria (word integrity, caesura alignment, stanza context — see below).
|
|
138
134
|
- **`≈ continuity; standalone: dactylic tetrameter`** — this line, taken
|
|
139
|
-
alone, fits dactylic a hair better; but the stanza
|
|
140
|
-
line fits amphibrachic nearly as well, so the continuity reading is
|
|
141
|
-
promoted to the base reading and the standalone result is kept as a note.
|
|
135
|
+
alone, fits dactylic a hair better; but if most of the other lines in the same stanza are amphibrachic and the line fits amphibrachic nearly as well as it fits dactylic, the primary reading is promoted to the stanza-dominant base meter, while the line-prevalent meter is co-registered as the "standalone" top fit via an added note.
|
|
142
136
|
- **`↔ aligns w/ stanza …`** — a weaker version of the same: the line stays
|
|
143
137
|
with its own meter but is flagged as compatible with the stanza's.
|
|
144
|
-
- **`♪ 4-beat accentual`** / `♪ 3-ictus dolnik` — a *rhythm note*: the stanza
|
|
145
|
-
|
|
146
|
-
with varying syllable counts (see "Beyond classical meters" below).
|
|
138
|
+
- **`♪ 4-beat accentual`** / `♪ 3-ictus dolnik` — a *rhythm note*: if the stanza
|
|
139
|
+
does not appear to be accentual-syllabic, but keeps a constant count of strong beats
|
|
140
|
+
with varying syllable counts (see "Beyond classical meters" below), it is marked as acentual.
|
|
147
141
|
- **`A`, `B(perfect)`, `·`** — the rhyme-scheme letter for the line's end
|
|
148
142
|
word, with the rhyme type when the line rhymes with an earlier one
|
|
149
143
|
(`perfect`, `rich`, `family`, `assonant`, `consonant`, `augmented`,
|
|
@@ -151,7 +145,7 @@ S1L2 m|-mww|sxx|mwm|s amphibrachic tetrameter (dact 1.21 · amph 1.17 ·
|
|
|
151
145
|
- **`❡ ballad stanza (ABCB, 4·3)`** — a stanza-level *form* verdict (shown in
|
|
152
146
|
the stanza header): ballad stanza, blank verse, couplet, limerick,
|
|
153
147
|
Shakespearean/Petrarchan sonnet, terza rima, etc.
|
|
154
|
-
- **Certainty / fit %** (detailed view) — the share of the line
|
|
148
|
+
- **Certainty / fit %** (detailed view) — the share of the line realized by
|
|
155
149
|
clean, unsubstituted feet, tempered by phrase-edge agreement. A perfectly
|
|
156
150
|
regular line reads 100%; real verse usually lands between 50 and 90.
|
|
157
151
|
|
|
@@ -159,99 +153,52 @@ S1L2 m|-mww|sxx|mwm|s amphibrachic tetrameter (dact 1.21 · amph 1.17 ·
|
|
|
159
153
|
|
|
160
154
|
## How it works: the scansion pipeline
|
|
161
155
|
|
|
162
|
-
Most automatic scanners pattern-match syllable counts against meter templates.
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
word
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
*
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
and archaic *-'d* / *-'st* forms (*fix'd*, *stopp'st*) keep their elided
|
|
189
|
-
syllable counts.
|
|
190
|
-
|
|
191
|
-
**3. The prosodic hierarchy (how the line phrases).**
|
|
192
|
-
Words are grouped the way speech groups them: each content word attracts its
|
|
193
|
-
function-word satellites into a **clitic group** (CP); clitic groups join into
|
|
194
|
-
**phonological phrases** (PP) along the syntactic dependencies; phrases join
|
|
195
|
-
into **intonational units** (IU) bounded by major punctuation. Crucially, the
|
|
196
|
-
**line is the scansion domain**: a verse line containing several grammatical
|
|
197
|
-
sentences is still ONE metrical unit (the internal full stops become strong
|
|
198
|
-
caesurae), and quotation marks are *not* treated as prosodic breaks.
|
|
156
|
+
Most automatic scanners pattern-match syllable counts against meter templates, or "from the outside in": count syllables, then match the count and a guessed stress pattern against a list of meter templates. Calliope TS instead follows the **phonological scansion** method. Phonological scansion works "from the inside out": it derives the line's normative spoken prominence first, then fits meters to it.
|
|
157
|
+
|
|
158
|
+
Two simple principles carry a lot of the work here, both articulated in Bruce Hayes and Abigail Kaun's study of how words are set to music (*The Role of Phonological Phrasing in Sung and Chanted Verse*, 1996):
|
|
159
|
+
|
|
160
|
+
1. **The ends of phonological units is what matters the most (in English, at least).**: Stresses at the *right edges* of prosodic units are more reliable metrical evidence. Generative metrics has long summarized this as **"beginnings free, endings strict."**
|
|
161
|
+
|
|
162
|
+
2. **Bigger units matter more.**
|
|
163
|
+
So, a stress at the end of a whole intonational unit is stronger evidence than one at the end of a phonological phrase, which is stronger evidence than the distribution of a given clitic phrase, which is more significant than the pattern of an individual word (however longer polysyllabic words may likewise hold more "weight" here). And in English as a whole, the pattern generally leans to the right (with certain significant exceptions, like numerous classes of compound expressions). But this bias as such aligns with the infamous iambic inclination.
|
|
164
|
+
|
|
165
|
+
Bruce Hayes himself (2005) and Gareth McAleese (2007/2008) built the first faithful algorithmic/computational implementations of a verse scansion procedure around those two ideas. Calliope TS re-implements that architecture on a modern JavaScript/TypeScript stack, while attempting to push it into distinctive directions. Among these: deliberately looser pre-attunement to standard iamb-centered English canons (while preserving and seeking to refine English phonological alignment accuracy); better accommodation of World poetry in meter-matching English translation (in other words, English canon levels of iambic base meter predominance should not be pre-assumed for Englished World (aka "Worldish") poetry canons); likewise, the mechanics of Calliope TS proceed from a choice not to essentialize ternary meters as inherently rare solely from English canon distributions (statistical fatalism); we, furthermore, aim to extend scansion accuracy over accentual verse forms; and, beyond scansion itself, hope to gradually incorporate nuanced and diversified identification of a broad range of poetic forms and devices (currently supported: rhyme types; in the future: alliterations, anaphoras, trope/cliche identifications, and more).
|
|
166
|
+
|
|
167
|
+
|
|
168
|
+
The current pipeline has eight stages.
|
|
169
|
+
|
|
170
|
+
**1. Grammatical parsing.**
|
|
171
|
+
The line is tokenized, part-of-speech tagged, and dependency-parsed — that is, the engine works out which word grammatically governs which (subject of what verb, object of what preposition) — using the FinNLP family of libraries (`lexed`, `en-pos`, `en-parse`). Two correction layers sit inside this stage,
|
|
172
|
+
First, because poetry tends to break part-of-speech and grammatical dependency taggers in predictable ways, a *tag-repair* pass fixes systematic errors before the dependency tree is built (this appropriately accounts for rare exotics and awkward/shifty commonplaces alike: from archaic forms like *thou/thy/doth/wherefore*, to the pronoun *I*, to perfect-tense participles like *had quit*).
|
|
173
|
+
Then we leverage a *tree-repair* pass (using the [depedits](https://www.npmjs.com/package/depedits) rule engine, our TypeScript port of the DepEdit library, originally in Python), which fixes systematic phrasal role attachment errors (e.g. noun compounds parsed as double objects, and the like). Hyphenated compounds and contractions (like *we'll*, *don't*, archaic *fix'd*, etc) are re-merged into single metrical words.
|
|
174
|
+
|
|
175
|
+
**2. Lexical stress.**
|
|
176
|
+
Every word is looked up for its pronunciation — syllable count, primary/secondary/unstressed pattern, syllable weights, vowel quantities — via our [nounsing-pro](https://www.npmjs.com/package/nounsing-pro) NLP toolkit, build over a full-scope CMU dictionary augmented with phonological and morphological data: syllable count, stress pattern (primary / secondary / unstressed), syllable weights, consonant types, morphological complexity and
|
|
177
|
+
vowel quantities. Words not in the dictionary go through a morphological fallback (strip a productive suffix, look up the stem, restore) coupled with a quantity-sensitive English Stress Rule. Poetic elisions are honored: *heav'n* is parsed as one syllable, so is *o'er*, *th'expense* as two, *'tis/'twas* reduces, while archaic *-'d* / *-'st* forms (*fix'd*, *stopp'st*) retain their elided syllable counts.
|
|
178
|
+
|
|
179
|
+
**3. The prosodic hierarchy.**
|
|
180
|
+
Words are grouped the way speech groups them, in the nested structure linguists call the prosodic hierarchy (Selkirk 1978; Hayes 1989):
|
|
181
|
+
Each content word attracts its function-word satellites into a **clitic group** (CP); clitic groups are joined into **phonological phrases** (PP) in accordance with syntactic inter-dependencies and primacies parsed earlier; phrases are organized into **intonational units** (IU) bounded by major punctuation or/and delineation. Crucially, the **line is the scansion domain**: a verse line containing several grammatical sentences is still parsed as a singular metrical unit (the internal full stops are treated as strong caesurae).
|
|
199
182
|
|
|
200
183
|
**4. Phrase-level stress rules.**
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
of
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
Following McAleese's central insight, the stresses at the *right edges* of
|
|
210
|
-
prosodic units are the reliable ones — speakers may start a phrase loosely
|
|
211
|
-
but they land its ending. Each unit contributes its right-edge "key stress"
|
|
212
|
-
with a weight (intonational unit > phrase > long word > clitic group), and
|
|
213
|
-
meters that place beats on those key stresses are rewarded.
|
|
214
|
-
|
|
215
|
-
**6. Meter fitting (dynamic programming).**
|
|
216
|
-
For each of seven candidate meters — iambic, trochaic, anapestic, dactylic,
|
|
217
|
-
**amphibrachic**, bacchic, spondaic — the engine finds the optimal division of
|
|
218
|
-
the line into feet, using that meter's full inventory of legitimate
|
|
219
|
-
variations: inversions at line-start or after a caesura, pyrrhic and spondaic
|
|
220
|
-
substitutions, catalexis (truncated final foot), anacrusis (extrametrical
|
|
221
|
-
upbeat), feminine endings, acephalous openings. Each syllable is scored
|
|
222
|
-
against the metrical position it lands in (a strong syllable in a beat slot
|
|
223
|
-
is ideal; a reduced clitic forced onto a beat is the cardinal violation), and
|
|
224
|
-
an **Attridge promotion** rule lets a weak syllable carry a beat when it is
|
|
225
|
-
flanked by even weaker ones (*"happens to BE a French poet"*) — which is how
|
|
226
|
-
real readers actually deliver such lines.
|
|
184
|
+
Several well-established rules of *English stress* mediate dictionary-derived lexical stresses within the consolidated phonological/phrasal context: primarily, the **compound stress rule** (left element generally stressed, *CITY hall*, with various exceptions), the **nuclear stress rule** (the last content word of an intonational unit receives a stress boost), and a set of **clash resolutions** (two adjacent strong syllables cannot both keep full prominence — one yields, chosen by syntactic direction). The result is mapped onto the five-tier `x w n m s` scale.
|
|
185
|
+
|
|
186
|
+
**5. Key stresses.**
|
|
187
|
+
Following generative metrics, the stresses at the *right edges* of prosodic units are treated as more reliable — speakers may start a phrase loosely but they land its ending. Each unit contributes its right-edge "key stress" with a weight (intonational unit > phrase > long word / clitic group > short word ), and meters that place beats on those key stresses are promoted.
|
|
188
|
+
|
|
189
|
+
**6. Meter fitting.**
|
|
190
|
+
For each of seven candidate metrical foot types — iambic, trochaic, anapestic, dactylic, amphibrachic, bacchic, spondaic — the engine finds the optimal division of the line into feet, using that meter's inventory of most plausible variations/divergences: inversions at line-start or after a caesura, pyrrhic and spondaic foot substitutions, catalexis (truncated final foot), anacrusis (extrametrical upbeat), feminine endings, acephalous openings, and so forth. Each syllable is scored against the metrical position it lands in (a strong syllable in a beat slot
|
|
191
|
+
is ideal; while a reduced clitic forced onto a beat is perhaps the heaviest cardinal violation). An additional **promotion** rule (drawn from Derik Attridge) lets a weak syllable carry a beat when it is flanked by even weaker ones (*"happens to BE a French poet"*).
|
|
227
192
|
|
|
228
193
|
**7. Arbitration and context.**
|
|
229
|
-
The winning meter is not
|
|
230
|
-
- **Ternary siblings** (anapest / amphibrach / dactyl)
|
|
231
|
-
|
|
232
|
-
division avoids splitting words across feet and aligns with the line's
|
|
233
|
-
pauses, not by score noise.
|
|
234
|
-
- **Stanza consensus**: each stanza's dominant meter is identified (for
|
|
235
|
-
ternary verse, by the stanza's *anacrusis profile* — how many slack
|
|
236
|
-
syllables open the lines, following Russian metrics). A line that fits the
|
|
237
|
-
dominant meter nearly as well as its own standalone winner **adopts the
|
|
238
|
-
dominant meter** as its base reading, with the standalone reading preserved
|
|
239
|
-
as a note. Metrical continuity outranks a hair of fit score, exactly as it
|
|
240
|
-
does for a human scander.
|
|
194
|
+
The winning meter is not simply the top raw score:
|
|
195
|
+
- **Ternary siblings** (anapest / amphibrach / dactyl meters) may sometimes fit a line via an *identical* distribution of beats — the difference being only where one might draw the foot boundaries. In such a situation, the base meter determination is decided by which foot division avoids slicing through words and best aligns with the line's pauses.
|
|
196
|
+
- **Stanza consensus**: each stanza's dominant meter is identified. An additional consideration is taken into account for ternary meters at this point: *anacrusis profile* — how many unstressed syllables are found at the beginning of a given line, and the stanza as a whole (a sensible heuristic suggested by Russian metrics).
|
|
241
197
|
|
|
242
198
|
**8. Beyond classical meters.**
|
|
243
|
-
If a stanza's syllable counts vary while its strong-beat
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
between beats) or **taktovik** (1–3), the categories of Russian verse theory
|
|
247
|
-
that also fit much English song, ballad, and modernist verse. Free verse is
|
|
248
|
-
recognised both line-by-line and stanza-wide. Independently, a **rhyme
|
|
249
|
-
layer** classifies every line-end pair (perfect / rich / family / slant /
|
|
250
|
-
eye / … rhymes, masculine / feminine / dactylic), detects the rhyme scheme,
|
|
251
|
-
and a **form layer** names what the stanzas amount to: ballad stanza (rhyme
|
|
252
|
-
scheme *and* alternating 4·3 beats), blank verse (unrhymed iambic
|
|
253
|
-
pentameter), couplets, quatrains, limerick, rhyme royal, Shakespearean or
|
|
254
|
-
Petrarchan sonnet, terza rima.
|
|
199
|
+
If a stanza's syllable counts vary significantly while its strong-beat count stays constant, the stanza is read as **accentual verse** , rather than classically footed accentual-syllabic (aka syllabotonic), and labeled as (`n-beat accentual`).
|
|
200
|
+
|
|
201
|
+
Alongside this, a **rhyme layer** classifies every line-end pair (perfect / rich / family / slant /eye / … rhymes, in masculine / feminine / dactylic shapes), detects the poem's rhyme scheme (if discernible), as well as its apparent **poetic form** (if documented by us). For now, the range of supported forms is very limited and the mechanics of discernment leave much to be desired. As of this version, the engine may (when particularly inspired) identify a ballad stanza, blank verse (unrhymed iambic pentameter), couplets, quatrains, limericks, rhyme royal, Shakespearean or Petrarchan sonnets, and Dante-style terza rima.
|
|
255
202
|
|
|
256
203
|
---
|
|
257
204
|
|
|
@@ -353,20 +300,15 @@ interface PhonologicalScansionDetail {
|
|
|
353
300
|
}
|
|
354
301
|
```
|
|
355
302
|
|
|
356
|
-
Lower-level functions (`parseDocument`, `assignLexicalStress`,
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
individual pipeline stages. The optional Scandroid comparison engines
|
|
360
|
-
(Charles Hartman's "Corral the Weird" and "Maximize the Normal") are exported
|
|
361
|
-
from `calliope-ts/dist/scandroid.js`.
|
|
303
|
+
Lower-level functions (`parseDocument`, `assignLexicalStress`, `buildPhonologicalHierarchy`, `scoreMeters`, …) are exported from their modules under `calliope-ts/dist/*` for users who want to run or modify individual pipeline stages.
|
|
304
|
+
|
|
305
|
+
The optional Scandroid comparison engines (Charles Hartman's "Corral the Weird" and "Maximize the Normal") are exported from `calliope-ts/dist/scandroid.js`.
|
|
362
306
|
|
|
363
307
|
---
|
|
364
308
|
|
|
365
309
|
## Examples
|
|
366
310
|
|
|
367
|
-
**A Shakespeare sonnet** (`calliope-ts --reading sonnet130.txt`) — every line
|
|
368
|
-
identified as iambic pentameter; the scheme letters spell ABAB CDCD EFEF GG;
|
|
369
|
-
the stanza header reads `❡ Shakespearean Sonnet`.
|
|
311
|
+
**A Shakespeare sonnet** (`calliope-ts --reading sonnet130.txt`) — every line identified as iambic pentameter; the scheme letters spell ABAB CDCD EFEF GG; the stanza header reads `❡ Shakespearean Sonnet`.
|
|
370
312
|
|
|
371
313
|
**A ballad quatrain:**
|
|
372
314
|
|
|
@@ -377,82 +319,42 @@ And he stoppeth one of three.
|
|
|
377
319
|
Now wherefore stopp'st thou me?
|
|
378
320
|
```
|
|
379
321
|
|
|
380
|
-
→ lines of iambic tetrameter / trimeter, scheme `·A·A`, and the form verdict
|
|
381
|
-
`❡ ballad stanza (ABCB, 4·3)` — the rhyme scheme *and* the alternating
|
|
382
|
-
4-beat/3-beat design both check out.
|
|
322
|
+
→ lines of iambic tetrameter / trimeter, scheme `·A·A`, and the form verdict `❡ ballad stanza (ABCB, 4·3)` — the rhyme scheme *and* the alternating 4-beat/3-beat design both check out.
|
|
383
323
|
|
|
384
|
-
**Accentual verse** (Wyatt, *They flee from me*) — no classical meter
|
|
385
|
-
dominates and syllable counts vary, but every line carries four strong beats:
|
|
386
|
-
each line is annotated `♪ 4-beat accentual`.
|
|
324
|
+
**Accentual verse** (Wyatt, *They flee from me*) — no classical meter dominates and syllable counts vary, but every line carries four strong beats: each line is annotated `♪ 4-beat accentual`.
|
|
387
325
|
|
|
388
|
-
**Amphibrachic verse** (Nabokov wrote his poem "Exile" as a demonstration
|
|
389
|
-
of English amphibrachs — the `x S x` foot): stanza consensus reads the poem's
|
|
390
|
-
constant one-syllable anacrusis as amphibrachic, names near-tie lines
|
|
391
|
-
accordingly with `≈ continuity` notes, and reports the `aabccb` rhyme
|
|
392
|
-
envelope.
|
|
326
|
+
**Amphibrachic verse** (Nabokov wrote his poem "Exile" as a demonstration of English amphibrachs — the `x S x` foot): stanza consensus reads the poem's constant one-syllable anacrusis as amphibrachic, names near-tie lines accordingly with `≈ continuity` notes, and reports the `aabccb` rhyme envelope.
|
|
393
327
|
|
|
394
|
-
**Blank verse** (Frost, *Mending Wall*) — unrhymed lines, dominant iambic
|
|
395
|
-
pentameter: `❡ blank verse`.
|
|
328
|
+
**Blank verse** (Frost, *Mending Wall*) — unrhymed lines, dominant iambic pentameter: `❡ blank verse`.
|
|
396
329
|
|
|
397
330
|
---
|
|
398
331
|
|
|
399
332
|
## Background and lineage
|
|
400
333
|
|
|
401
|
-
|
|
402
|
-
McAleese's *Calliope*, developed for his M.Sc. at the Open University
|
|
403
|
-
(*"Improving Scansion with Syntax: an Investigation into the Effectiveness of
|
|
404
|
-
a Syntactic Analysis of Poetry by Computer using Phonological Scansion
|
|
405
|
-
Theory"*, Technical Report 2007/26, submitted 2008). McAleese's central idea:
|
|
406
|
-
scansion should be computed from a line's *phonology* — the prosodic
|
|
407
|
-
hierarchy and the stresses at the right edges of its units ("beginnings free,
|
|
408
|
-
endings strict") — rather than from orthographic pattern-matching. Calliope TS
|
|
409
|
-
re-implements that architecture on a modern Node.js stack and extends it.
|
|
410
|
-
|
|
411
|
-
**Scandroid (1996/2005).** Charles O. Hartman's Scandroid, a classic
|
|
412
|
-
foot-by-foot scanner (GNU GPL), is included as an optional comparison engine:
|
|
413
|
-
its "Corral the Weird" and "Maximize the Normal" algorithms can be run side
|
|
414
|
-
by side with the phonological scansion.
|
|
415
|
-
|
|
416
|
-
**Extensions beyond McAleese.** The five-tier stress gradient with a
|
|
417
|
-
zero-provision level; a unified dynamic-programming meter fitter with full
|
|
418
|
-
substitution inventories (and first-class **amphibrach** support); beat
|
|
419
|
-
promotion after Derek Attridge's beat/offbeat analysis; the dolnik/taktovik
|
|
420
|
-
classification from Russian verse theory (Gasparov); stanza-consensus and
|
|
421
|
-
anacrusis-profile naming; the rhyme and form layers; and the parse-correction
|
|
422
|
-
layers for verse-specific tagging.
|
|
423
|
-
|
|
424
|
-
**Data.** Lexical phonology comes from the augmented CMU dictionary published
|
|
425
|
-
as `nounsing-pro` (syllabification, stress transcription, syllable structure,
|
|
426
|
-
morphological stress classes). Parsing uses the FinNLP family. Dependency
|
|
427
|
-
repairs use `depedits`, a TypeScript port of the DepEdit rule engine.
|
|
428
|
-
|
|
429
|
-
Calliope TS is developed by **Aleksey Calvin** /
|
|
430
|
-
[SilverAgePoets.com](https://www.SilverAgePoets.com), with particular care for
|
|
431
|
-
verse traditions that standard English-centric tools marginalize: ternary
|
|
432
|
-
meters, Russian Silver-Age forms in translation, song lyrics, and accentual
|
|
433
|
-
verse.
|
|
334
|
+
The method implemented here substantially follows the example set by Gareth McAleese's *Calliope* (2007.2008), developed for his M.Sc. at the Open University (*"Improving Scansion with Syntax: an Investigation into the Effectiveness of a Syntactic Analysis of Poetry by Computer using Phonological Scansion Theory"*, Technical Report 2007/26, submitted 2008). For it, McAleese devises a computational scansion framework substantially grounded in the phonological scansion methodologies of UCLA's renowned linguist and phonologist **Bruce Hayes**, developed by him across the 1980s, 90s, and 2000s — most relevantly in *Extrametricality and English Stress* (1982), *The Phonology of Rhythm in English* (1984), *The Prosodic Hierarchy in Meter* (1989), the *Metrical Stress Theory* (1995), and *The Role of Phonological Phrasing in Sung and Chanted Verse* with Abigail Kaun (1996). Hayes in turn built on the groundwork laid by Halle & Chomsky, Liberman & Prince, and Kiparsky (some of the seminal Generative Metrics, Optimality Theory, and related domains. Most pertinent to approach taken up by McAleese (as well as ourselves presently) is Hayes's work from the early 1990s onward, in which he drew increasingly on the nascent **Optimality Theory** (OT) (much credit to Prince & Smolensky, whose *Optimality Theory: Constraint Interaction in Generative Grammar*, 1993/2002, much enriched the empirical toolkit of generative grammar-adjacent theory domains). In the 2000s Hayes would contribute to placing OT onto the more precise rails of **MaxEnt** (Maximum Entropy) methods. McAleese's work, however, preceded this turn. Backing up somewhat to peruse the field, it is worth acknowledging the remarkable breadth of synthesis McAleese draws on, which beyond those above-named, harnesses the influence of Paul Kiparsky (e.g. *The Rhythmic Structure of English Verse*, 1977), Kristin Hanson (*A Parametric Theory of Poetic Meter*, 1996), the prosodic-phrasing and stress-shift related work of Elisabeth Selkirk (1978), as well as studies by Richard Cureton (1992), Peter Groves (1998), and many others (see McAleese's paper at https://oro.open.ac.uk/90197/ for a full bibliography).
|
|
434
335
|
|
|
435
|
-
|
|
336
|
+
| Source | What it grounds in Calliope |
|
|
337
|
+
|---|---|
|
|
338
|
+
| Hayes & Kaun (1996) | the core method: right-edge key stresses, weighted by prosodic-unit size (stage 5) |
|
|
339
|
+
| Hayes (1989), *Prosodic Hierarchy in Meter* | the CP → PP → IU phrasing (stage 3) |
|
|
340
|
+
| Hayes (1982), *Extrametricality* | extrametrical syllables and the OOV English Stress Rule (stage 2) |
|
|
341
|
+
| Chomsky & Halle (1968); Liberman & Prince (1977); Hayes (1984) | the lexical and phrasal stress rules — compound, nuclear, clash (stage 4) |
|
|
342
|
+
| Prince & Smolensky (1993/2002); Hayes et al., MaxEnt | the constraint-based, weighted meter fitter (stages 5–7) |
|
|
343
|
+
| Selkirk (1978) | the phonological phrase as a prosodic constituent (stage 3) |
|
|
344
|
+
| Attridge, *The Rhythms of English Poetry* / *The Rhythms of the English Dolnik* | beat/offbeat promotion (stage 6) and the dolnik (stage 8) |
|
|
345
|
+
| Gasparov, *A History of European Versification* | the dolnik / taktovik / accentual taxonomy (stage 8) |
|
|
346
|
+
| McAleese (2008) | the core outline for the scansion procedure, with further solutions drawn by us from Hayes 2008 & Prosodic (MaxEnt weighing), as well as original extrapolations |
|
|
347
|
+
|
|
348
|
+
**Scandroid (1996/2005).** Charles O. Hartman's Scandroid, a classic foot-by-foot scanner (GNU GPL), is included as an optional comparison engine: its "Corral the Weird" and "Maximize the Normal" algorithms can be run side by side with the phonological scansion.
|
|
436
349
|
|
|
437
|
-
|
|
350
|
+
Calliope TS is developed by **Aleksey Calvin** / [SilverAgePoets.com](https://www.SilverAgePoets.com)
|
|
438
351
|
|
|
439
|
-
|
|
440
|
-
View is usable as a reading aid in itself. Ternary meters (anapest /
|
|
441
|
-
amphibrach / dactyl) are first-class citizens, not afterthoughts. Accentual
|
|
442
|
-
and dolnik verse get a real classification instead of a "free verse" shrug.
|
|
443
|
-
Whole-poem context (stanza consensus, rhyme, form) informs line verdicts the
|
|
444
|
-
way it does for human readers.
|
|
352
|
+
---
|
|
445
353
|
|
|
446
354
|
**Limitations to know about.**
|
|
447
|
-
- English only (the dictionary and parser are English; other languages will
|
|
448
|
-
|
|
449
|
-
- Stress-doublet words (*rebel*, *content*, names like *Hugo*) are read with
|
|
450
|
-
their dictionary stress; a rhyme-driven correction is on the roadmap.
|
|
355
|
+
- English only (the dictionary and parser are English; other languages will produce nonsense rather than errors).
|
|
356
|
+
- Stress-doublet words (*rebel*, *content*, names like *Hugo*) are read with their dictionary stress; a correction is on the roadmap.
|
|
451
357
|
- Rare or foreign proper names fall back to rule-based stress guesses.
|
|
452
|
-
- The form layer recognises the common stanza forms; it does not yet attempt
|
|
453
|
-
villanelle/pantoum repetition checking or syllabic forms.
|
|
454
|
-
- Meter identification on single lines without context is genuinely harder
|
|
455
|
-
than with stanza context — when possible, scan whole poems.
|
|
456
358
|
|
|
457
359
|
---
|
|
458
360
|
|
|
@@ -468,18 +370,12 @@ node trials/mcaleese_benchmark.mjs # McAleese's own trial poems + expert keys
|
|
|
468
370
|
node trials/corpus_benchmark.mjs # litlab / prosodic / epg64 meter corpora
|
|
469
371
|
```
|
|
470
372
|
|
|
471
|
-
The repository's `AGENTS.md` carries a dated engineering log of every
|
|
472
|
-
substantive change with its rationale and verification.
|
|
473
|
-
|
|
474
373
|
---
|
|
475
374
|
|
|
476
375
|
## License and credits
|
|
477
376
|
|
|
478
377
|
Apache-2.0. © Aleksey Calvin Tsukanov / SilverAgePoets.com.
|
|
378
|
+
My email: alekseycalvin@gmail.com
|
|
479
379
|
|
|
480
|
-
Methodological debts: Gareth McAleese (Calliope, the phonological scansion
|
|
481
|
-
|
|
482
|
-
rhythm and the English dolnik); M. L. Gasparov (dolnik/taktovik taxonomy);
|
|
483
|
-
Bruce Hayes, Paul Kiparsky, and the generative-metrics tradition (stress
|
|
484
|
-
theory, syllable quantity, extrametricality); the CMU Pronouncing Dictionary
|
|
485
|
-
and its `nounsing-pro` augmentation.
|
|
380
|
+
Methodological and conceptual debts: Bruce Hayes (1982/1984/1995/1996 with Abigail Kaun/2005) (the phonological scansion procedure as such, extrametricality insights, text-setting methodologies, MaxEnt OT, and who knows what else), Gareth McAleese (for a single 2008 paper, for detailing the original Calliope implementation, for exhibiting a remarkable field-spanning purview, an uncanny industriousness, and an uncommon – perhaps a tad obsessive – dedication to testing, refining, fusing, and extending all sorts of methodologies in a single-minded pursuit of bringing constraint-based computational scansion far beyond the best documented practices and results at that time; and for so obviously succeeding, if only to seemingly vanish from the field as abruptly and unreservedly as he entered and absorbed it*); Charles O. Hartman (Scandroid); Claire Moore Cantwell (morphological/phonological tagging algorithms), Austin Pursley (implementing finer-grained rhyme-matching heuristics over a corpus), Allison Parrish (Pronouncing-py and being a real life computational poet hero), Derek Attridge (beat/offbeat rhythm theory and insightful writings on the English dolnik); M. L. Gasparov (dolnik/taktovik taxonomy); the compilers of the CMU Pronouncing Dictionary; the makers of Prosodic (Heuser et al, for establishing an admirable state-of-the-art to compare against, differentiate from, and hopefully surpass in due time, in select ways), as well as broader generative-metrics, constraint-based metrics, and OT traditions, including Kiparsky, Prince & Smolensky, Groves, Blumenfeld, Lilja, Chomsky & Halle, Fabb & Halle (rule-based grid scansion theory), Einarsson (Metremic theory), Russom (Universalist metrics), K. M. Ryan (gradient syllable weight), big daddy Jakobson who had once roped the whole world with subtle strings and often hung out with Mayakovsky, and many others.
|
|
381
|
+
*Gareth McAleese: If you're reading this, please do email me!
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { ClsWord, IntonationalUnit } from './types.js';
|
|
2
|
+
export type CaesuraKind = 'hard' | 'soft';
|
|
3
|
+
/** A caesura with its graded boundary strength (0..1, NSBR-scaled), so the display
|
|
4
|
+
* can colour the mark by how strong the underlying prosodic break is. */
|
|
5
|
+
export interface CaesuraInfo {
|
|
6
|
+
kind: CaesuraKind;
|
|
7
|
+
strength: number;
|
|
8
|
+
}
|
|
9
|
+
/**
|
|
10
|
+
* Caesura positions for a line, keyed by the syllable index AFTER which the pause
|
|
11
|
+
* falls (= number of syllables to its left).
|
|
12
|
+
* • 'hard' — an overt break at an Intonational-Unit boundary.
|
|
13
|
+
* • 'soft' — a single INFERRED medial caesura for a punctuation-free line.
|
|
14
|
+
* Candidates are the boundaries just before a phrase/clause onset
|
|
15
|
+
* (PHRASE_ONSET_POS); the one nearest the line's midpoint that lies in the
|
|
16
|
+
* central third AND coincides with a foot boundary wins — so it is medial,
|
|
17
|
+
* never mid-foot, and consistent across structurally-parallel lines. Read in
|
|
18
|
+
* LINEAR order (robust to clitic-group reordering); needs a line of ≥ 8
|
|
19
|
+
* syllables.
|
|
20
|
+
*/
|
|
21
|
+
export declare function computeCaesurae(words: ClsWord[], ius: IntonationalUnit[], scansion?: string): Map<number, CaesuraInfo>;
|
|
22
|
+
/**
|
|
23
|
+
* The words that immediately PRECEDE a caesura in a line — i.e. each word whose
|
|
24
|
+
* cumulative syllable count lands exactly on a caesura position. Used by the
|
|
25
|
+
* rhyme layer for pre-caesural internal-rhyme detection. Returned in linear
|
|
26
|
+
* (reading) order; the caesura kind is paired so callers can weight hard vs
|
|
27
|
+
* inferred breaks if they wish.
|
|
28
|
+
*/
|
|
29
|
+
export declare function preCaesuralWords(words: ClsWord[], ius: IntonationalUnit[], scansion?: string): {
|
|
30
|
+
word: ClsWord;
|
|
31
|
+
kind: CaesuraKind;
|
|
32
|
+
}[];
|
|
33
|
+
//# sourceMappingURL=caesura.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"caesura.d.ts","sourceRoot":"","sources":["../src/caesura.ts"],"names":[],"mappings":"AAaA,OAAO,EAAE,OAAO,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAC;AAIvD,MAAM,MAAM,WAAW,GAAG,MAAM,GAAG,MAAM,CAAC;AAE1C;0EAC0E;AAC1E,MAAM,WAAW,WAAW;IAAG,IAAI,EAAE,WAAW,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAC;CAAE;AAyCrE;;;;;;;;;;;GAWG;AACH,wBAAgB,eAAe,CAAC,KAAK,EAAE,OAAO,EAAE,EAAE,GAAG,EAAE,gBAAgB,EAAE,EAAE,QAAQ,CAAC,EAAE,MAAM,GAAG,GAAG,CAAC,MAAM,EAAE,WAAW,CAAC,CAuGtH;AAED;;;;;;GAMG;AACH,wBAAgB,gBAAgB,CAC9B,KAAK,EAAE,OAAO,EAAE,EAAE,GAAG,EAAE,gBAAgB,EAAE,EAAE,QAAQ,CAAC,EAAE,MAAM,GAC3D;IAAE,IAAI,EAAE,OAAO,CAAC;IAAC,IAAI,EAAE,WAAW,CAAA;CAAE,EAAE,CAYxC"}
|