rapier-markdown-kit 1.1.102 → 1.1.104

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.
Files changed (60) hide show
  1. package/LICENSE +2 -2
  2. package/README.md +213 -53
  3. package/dist/agent/vendor/hyphen-en-us/LICENSE +14 -0
  4. package/dist/agent/vendor/hyphen-en-us/SOURCE.json +33 -0
  5. package/dist/agent/vendor/hyphen-en-us/hyph-en-us.hyp.txt +14 -0
  6. package/dist/agent/vendor/hyphen-en-us/hyph-en-us.pat.txt +4938 -0
  7. package/dist/agent/vendor/hyphen-en-us/patterns.js +25 -0
  8. package/dist/agent/vendor/pretext/LICENSE +208 -0
  9. package/dist/agent/vendor/pretext/NOTICE +26 -13
  10. package/dist/agent/vendor/pretext/SOURCE.json +213 -45
  11. package/dist/agent/vendor/pretext/analysis.js +675 -1224
  12. package/dist/agent/vendor/pretext/entry-geometry.js +183 -0
  13. package/dist/agent/vendor/pretext/gecko-line-breaks.js +688 -0
  14. package/dist/agent/vendor/pretext/generated/engine-break-data.js +57 -0
  15. package/dist/agent/vendor/pretext/generated/webkit-generic-families.js +80 -0
  16. package/dist/agent/vendor/pretext/graphemes.js +98 -0
  17. package/dist/agent/vendor/pretext/han-kerning.js +253 -0
  18. package/dist/agent/vendor/pretext/layout.js +352 -290
  19. package/dist/agent/vendor/pretext/line-break.js +1154 -588
  20. package/dist/agent/vendor/pretext/line-breaks.js +892 -0
  21. package/dist/agent/vendor/pretext/line-text.js +81 -39
  22. package/dist/agent/vendor/pretext/measurement.js +1105 -176
  23. package/dist/agent/vendor/pretext/prepare.js +807 -0
  24. package/dist/agent/vendor/pretext/rich-inline.js +1242 -273
  25. package/dist/agent/will.mjs +2 -0
  26. package/dist/kit/assets.mjs +5 -1
  27. package/dist/kit/conformance/run.mjs +4 -4
  28. package/dist/kit/export-fonts.mjs +26 -11
  29. package/dist/kit/index.mjs +1 -0
  30. package/dist/kit/ledger/carried.mjs +9 -7
  31. package/dist/kit/ledger/data.mjs +73 -13
  32. package/dist/kit/ledger/format.mjs +166 -53
  33. package/dist/kit/ledger/hash.mjs +75 -18
  34. package/dist/kit/ledger/history.mjs +143 -115
  35. package/dist/kit/ledger/inverse-source.mjs +158 -19
  36. package/dist/kit/ledger/journal-records.mjs +292 -67
  37. package/dist/kit/model.mjs +1 -1
  38. package/dist/kit/pdf-glyphs.mjs +4 -4
  39. package/dist/kit/render-markdown.mjs +259 -122
  40. package/dist/kit/render-sanitize.mjs +24 -4
  41. package/dist/kit/render-work.mjs +99 -20
  42. package/dist/kit/render.mjs +101 -65
  43. package/dist/kit/typography.mjs +2 -0
  44. package/dist/layout/hyphenation.mjs +127 -0
  45. package/dist/layout/line-plan.mjs +88 -96
  46. package/dist/layout/model.mjs +61 -80
  47. package/dist/layout/paragraph-fit.mjs +191 -0
  48. package/dist/layout/preparation.mjs +373 -0
  49. package/dist/layout/prepared-paragraph.mjs +223 -0
  50. package/dist/layout/typography.mjs +345 -111
  51. package/dist/packages/rapier-diff/index.mjs +288 -196
  52. package/dist/spec/document-fonts.mjs +13 -4
  53. package/dist/spec/md-assets.mjs +149 -30
  54. package/dist/spec/md-layout.mjs +5 -2
  55. package/dist/spec/md-marks.mjs +218 -3
  56. package/dist/spec/md-source.mjs +122 -0
  57. package/package.json +2 -1
  58. package/style.css +9 -0
  59. package/dist/agent/vendor/pretext/bidi.js +0 -151
  60. package/dist/agent/vendor/pretext/generated/bidi-data.js +0 -3831
@@ -0,0 +1,183 @@
1
+ /*! Pretext Unreleased (bac1774c0) | MIT; BSD/Unicode/ICU notices in LICENSE | Copyright (c) 2026 Pretext contributors */
2
+ // Fresh-line geometry, or entry geometry: the widths a line takes where it starts inside a
3
+ // segment cut between graphemes, at or inside a stretch of it that holds a default-ignorable code
4
+ // point (a ZWNJ, a word joiner, a bidi mark). Shaping looks past such a character, so the text
5
+ // after the cut, shaped afresh at the line's start, can measure otherwise than the segment's own
6
+ // advances give (RESEARCH.md, Widths After A Line Break). For each such start, preparation
7
+ // measures the text from the start through the first whole grapheme past that stretch, the
8
+ // anchor, in at most three prefixes (the entry's head); past the anchor the widths go on by the
9
+ // segment's advances. The walkers (src/line-break.ts) ask an entry whether the segment's whole
10
+ // tail fits the line (admissionFit), which Blink reads from the tail as measured afresh and Gecko
11
+ // from the whole segment's width less the prefixes already placed (the profile's entryFitBasis),
12
+ // and, where it doesn't fit, how many graphemes do by the fresh prefixes. Only the desktop Blink
13
+ // and Gecko profiles observe entries, the browsers they were checked in, and a segment of more
14
+ // than 96 graphemes takes none (RESEARCH.md, Keeping Work Bounded).
15
+ import { findGraphemeEnds } from './graphemes.js'
16
+ import { getEngineProfile } from './measurement.js'
17
+
18
+ const defaultIgnorable = /\p{Default_Ignorable_Code_Point}/u
19
+ const MAX_GRAPHEMES = 96
20
+ const MAX_HEAD_ENDPOINTS = 3
21
+
22
+ // Whether a text holds a default-ignorable code point, without which no segment of it has entry
23
+ // geometry (observeSegmentEntries).
24
+ export function textMayHaveEntryGeometry(text ) {
25
+ return defaultIgnorable.test(text)
26
+ }
27
+
28
+
29
+
30
+
31
+
32
+
33
+
34
+
35
+
36
+ // The stretches of a segment that a default-ignorable affects, as intervals of the source text.
37
+ // The text without its default-ignorables (the projection) is cut into grapheme clusters, and the
38
+ // segment's own graphemes that one such cluster spans are joined into one interval. An interval
39
+ // is observed where it holds a default-ignorable, and leading default-ignorables join the first
40
+ // visible interval. The projection only picks the intervals: what is measured is the source text,
41
+ // and the segment's grapheme boundaries and breaks stay its own.
42
+ function affectedIntervals(text , endpoints ) {
43
+ const spans = []
44
+ const projected = []
45
+ const visibleRuns = /[^\p{Default_Ignorable_Code_Point}]+/gu
46
+ for (let match; (match = visibleRuns.exec(text)) !== null;) {
47
+ spans.push({ start: match.index, end: match.index + match[0].length })
48
+ projected.push(match[0])
49
+ }
50
+ // Map only the projected grapheme endpoints through retained source views.
51
+ // The last code unit maps before an ignored gap; the next start maps after it.
52
+ let spanIndex = 0
53
+ let projectedStart = 0
54
+ function sourceOffset(offset ) {
55
+ let span = spans[spanIndex]
56
+ while (offset >= projectedStart + span.end - span.start) {
57
+ projectedStart += span.end - span.start
58
+ span = spans[++spanIndex]
59
+ }
60
+ return span.start + offset - projectedStart
61
+ }
62
+ const joined = new Uint8Array(endpoints.length)
63
+ const visible = projected.join('')
64
+ const ends = new Int32Array(visible.length)
65
+ const count = findGraphemeEnds(getEngineProfile().graphemeTable, visible, 0, visible.length, ends)
66
+ let boundaryIndex = 1
67
+ for (let i = 0, projectedEnd = 0; i < count; i++) {
68
+ const start = sourceOffset(projectedEnd)
69
+ projectedEnd = ends[i]
70
+ const end = sourceOffset(projectedEnd - 1) + 1
71
+ while (boundaryIndex < endpoints.length && endpoints[boundaryIndex] <= start) boundaryIndex++
72
+ while (boundaryIndex < endpoints.length && endpoints[boundaryIndex] < end) joined[boundaryIndex++] = 1
73
+ }
74
+ const parts = []
75
+ let start = 0
76
+ for (let index = 1; index < endpoints.length; index++) {
77
+ if (joined[index] === 1) continue
78
+ const end = endpoints[index]
79
+ parts.push({ start, end, observe: defaultIgnorable.test(text.slice(start, end)) })
80
+ start = end
81
+ }
82
+ const leadingEnd = spans.length === 0 ? text.length : spans[0] .start
83
+ if (leadingEnd > 0 && leadingEnd < text.length) {
84
+ let firstVisiblePart = 0
85
+ while (parts[firstVisiblePart] .end <= leadingEnd) firstVisiblePart++
86
+ parts.splice(0, firstVisiblePart + 1, { start: 0, end: parts[firstVisiblePart] .end, observe: true })
87
+ }
88
+ return parts
89
+ }
90
+
91
+ // At most 96 original graphemes and three exact head queries per covered entry.
92
+ // Each source grapheme enters at most 3 + 2 + 1 measured prefixes across all
93
+ // starts, so submitted UTF-16 stays at most six times the source length.
94
+ // Preparation retains only numeric geometry for subsequent line walking.
95
+ export function observeSegmentEntries(
96
+ text ,
97
+ advances ,
98
+ letterSpacing ,
99
+ wholeWidth ,
100
+ fitBasis ,
101
+ measure ,
102
+ ) {
103
+ if (!defaultIgnorable.test(text) || advances.length > MAX_GRAPHEMES) return null
104
+ const ends = new Int32Array(text.length)
105
+ const count = findGraphemeEnds(getEngineProfile().graphemeTable, text, 0, text.length, ends)
106
+ if (count > MAX_GRAPHEMES) return null
107
+ const endpoints = [0]
108
+ for (let i = 0; i < count; i++) endpoints.push(ends[i] )
109
+ if (endpoints.length !== advances.length + 1) throw new Error('Entry and release grapheme cursors differ')
110
+ const parts = affectedIntervals(text, endpoints)
111
+ const terminalPrefixes = [0]
112
+ for (const advance of advances) terminalPrefixes.push(terminalPrefixes[terminalPrefixes.length - 1] + advance + letterSpacing)
113
+ const entries = Array.from({ length: advances.length }, () => null)
114
+ let partIndex = 0
115
+ let hasEntries = false
116
+ for (let start = 1; start < advances.length; start++) {
117
+ const sourceStart = endpoints[start]
118
+ while (partIndex < parts.length && parts[partIndex] .end <= sourceStart) partIndex++
119
+ const part = parts[partIndex]
120
+ // A start is observed inside an affected interval. The anchor, the first whole grapheme
121
+ // past that interval, is measured after it as its right context, and a line that starts
122
+ // at the anchor takes an entry only where the anchor's own interval is affected.
123
+ if (part === undefined || !part.observe || sourceStart < part.start) continue
124
+ let anchor = start + 1
125
+ while (anchor < advances.length && endpoints[anchor] <= part.end) anchor++
126
+ // An entry needs that whole grapheme. An interval that ends the segment has none, so
127
+ // its starts take no entry: what a line start measures with nothing after it hasn't
128
+ // been checked against a browser. Nor does a start whose head would take more than
129
+ // three prefixes.
130
+ if (endpoints[anchor] <= part.end || anchor - start > MAX_HEAD_ENDPOINTS) continue
131
+ const head = []
132
+ let complete = true
133
+ for (let end = start + 1; end <= anchor; end++) {
134
+ const query = text.slice(sourceStart, endpoints[end])
135
+ const width = measure(query)
136
+ if (width === null || !Number.isFinite(width)) { complete = false; break }
137
+ head.push(width)
138
+ }
139
+ if (!complete) continue
140
+ let admissionFit
141
+ switch (fitBasis) {
142
+ case 'fresh':
143
+ admissionFit = head[head.length - 1] +
144
+ (terminalPrefixes[advances.length] - terminalPrefixes[anchor] )
145
+ break
146
+ case 'original':
147
+ admissionFit = wholeWidth + letterSpacing - terminalPrefixes[start]
148
+ break
149
+ }
150
+ entries[start] = { head, admissionFit }
151
+ hasEntries = true
152
+ }
153
+ return hasEntries ? { terminalPrefixes, entries } : null
154
+ }
155
+
156
+ // Where a fresh line that starts at grapheme `start` of a segment ends, by the entry observed
157
+ // there: past the segment's end (end + 1) where the whole tail is admitted and the line goes on
158
+ // with the text after it, else after the last fresh prefix that fits, keeping the first grapheme.
159
+ // `end` then means the prefixes ran out, and the line ends with the segment.
160
+ export function getFreshLineEnd(geometry , start , end , fitLimit ) {
161
+ if (geometry.entries[start] .admissionFit <= fitLimit) return end + 1
162
+ let g = start + 1
163
+ while (g < end && getSegmentEntryWidth(geometry, start, g + 1) <= fitLimit) g++
164
+ return g
165
+ }
166
+
167
+ // The width of a segment's graphemes from `start` to `end` on a fresh line that starts at
168
+ // `start`, with the letter spacing after the last of them. Null where no entry was observed,
169
+ // as at the segment's own start; an observed 0 is a width, and the prefixes needn't grow.
170
+ export function getSegmentEntryWidth(
171
+ geometry ,
172
+ start ,
173
+ end ,
174
+ ) {
175
+ if (geometry === null) return null
176
+ const entry = geometry.entries[start]
177
+ if (entry === null) return null
178
+ if (end === start) return 0
179
+ const anchor = start + entry.head.length
180
+ if (end <= anchor) return entry.head[end - start - 1]
181
+ return entry.head[entry.head.length - 1] +
182
+ (geometry.terminalPrefixes[end] - geometry.terminalPrefixes[anchor] )
183
+ }