@sushichan044/kg-core 0.9.5 → 0.10.1
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 +100 -25
- package/dist/index.d.mts +19785 -6601
- package/dist/index.mjs +2 -2
- package/dist/lint.mjs +1 -1
- package/dist/novel-composer-D_orH6ET.mjs +3393 -0
- package/dist/plugin.d.mts +130 -2
- package/dist/plugin.mjs +29 -3
- package/dist/{novel-composer-DhycV9B3.d.mts → presentation-kind-BwIZFSZS.d.mts} +5964 -2705
- package/dist/{question-or-exclamation-spacing-1tnZ4CLb.mjs → question-or-exclamation-spacing-Cp3eOGlA.mjs} +5 -1
- package/package.json +5 -5
- package/dist/novel-composer-BC8W63vw.mjs +0 -2343
package/README.md
CHANGED
|
@@ -146,36 +146,58 @@ The composer classifies vertical text before measuring and breaking lines. Follo
|
|
|
146
146
|
[JLReq](https://www.w3.org/TR/jlreq/#mixed_text_composition_in_vertical_writing_mode),
|
|
147
147
|
upright Latin initials and abbreviations advance by one em per character, Western
|
|
148
148
|
words remain unbroken and render sideways, and two ASCII digits form one
|
|
149
|
-
tate-chu-yoko unit.
|
|
150
|
-
|
|
149
|
+
tate-chu-yoko unit. Each render unit carries its selected `presentation` as a
|
|
150
|
+
string. A `CombinedGlyphUnit` renders the two digits together; the composer owns
|
|
151
|
+
that decision, so renderers do not compare source group ranges.
|
|
151
152
|
|
|
152
153
|
An upright Western character sets solid against the kana or kanji beside it rather than
|
|
153
154
|
taking the quarter em 3.2.6 puts around a sideways run, following JLReq 3.2.4: it classes
|
|
154
155
|
with kanji, the same way 3.2.5 classes a tate-chu-yoko run. `QR` and `URL` set upright by
|
|
155
156
|
this rule read flush against their surrounding Japanese text, the way a kanji compound does.
|
|
156
157
|
|
|
157
|
-
The default
|
|
158
|
-
ASCII advances by one em;
|
|
159
|
-
advance by half an em.
|
|
160
|
-
|
|
158
|
+
The default `logicalRunMeasurer` uses East Asian Width in a Japanese context.
|
|
159
|
+
Upright ASCII advances by one em; sideways ASCII and tate-chu-yoko members
|
|
160
|
+
advance by half an em. Measurement is synchronous and DOM-independent.
|
|
161
|
+
|
|
162
|
+
Supply a `RunMeasurer` through the plugin entry when metrics are already available:
|
|
161
163
|
|
|
162
164
|
```ts
|
|
163
|
-
import { createNovelComposer } from "@sushichan044/kg-core/plugin";
|
|
164
|
-
|
|
165
|
-
const composer = createNovelComposer({
|
|
166
|
-
measurer: (request) => ({
|
|
167
|
-
advanceEm: measureWithAvailableFont(request.text, {
|
|
168
|
-
role: request.role,
|
|
169
|
-
fontPreset: request.fontPreset,
|
|
170
|
-
writingMode: request.writingMode,
|
|
171
|
-
...(request.role === "base" ? { presentation: request.presentation } : {}),
|
|
172
|
-
}),
|
|
173
|
-
}),
|
|
174
|
-
});
|
|
165
|
+
import { createNovelComposer, logicalRunMeasurer } from "@sushichan044/kg-core/plugin";
|
|
166
|
+
|
|
167
|
+
const composer = createNovelComposer({ measurer: logicalRunMeasurer });
|
|
175
168
|
```
|
|
176
169
|
|
|
177
|
-
|
|
178
|
-
|
|
170
|
+
`MeasurementRequest` includes `text`, `kind` (`base` or `ruby`), `presentation`,
|
|
171
|
+
`fontPreset`, body `fontSizePt`, `writingMode`, and `scale`. A provider returns
|
|
172
|
+
measurements in body em and applies `scale` once: `1` for base text, `0.5` for ruby.
|
|
173
|
+
Measured widths exclude punctuation box adjustments, pair spacing, hanging, and
|
|
174
|
+
ruby expansion.
|
|
175
|
+
|
|
176
|
+
`RunMeasurement` has two variants:
|
|
177
|
+
|
|
178
|
+
- `{ kind: "advance", advanceEm }` supplies aggregate width. The composer retains
|
|
179
|
+
per-grapheme measurement for positioning; it never divides a nonadditive run
|
|
180
|
+
width equally among its members. Complete reading widths still inform base
|
|
181
|
+
widening.
|
|
182
|
+
- `{ kind: "clustered", advanceEm, clusters }` supplies authoritative cluster
|
|
183
|
+
positions. Each `MeasuredCluster` has a request-local `textRange`, `layoutSpan`,
|
|
184
|
+
and `renderSpan`. Use `MeasurementTextRange.of({ start, end })` to construct the
|
|
185
|
+
branded UTF-16 range. Clusters partition text at grapheme boundaries and layout
|
|
186
|
+
advance within `1e-9`; render spans can overlap and overhang. The composer does
|
|
187
|
+
not remeasure cluster members or break a line inside a cluster.
|
|
188
|
+
|
|
189
|
+
A multi-grapheme sideways cluster, such as a shaped `ffi` ligature, is drawn in a
|
|
190
|
+
combined run with shared source positions. Upright `QR` and `URL` are orientation
|
|
191
|
+
choices; they do not by themselves imply a shared cluster. The combined-unit
|
|
192
|
+
contract supports sideways text and tate-chu-yoko. A provider result that cannot
|
|
193
|
+
be represented by that contract is refused rather than split or approximated.
|
|
194
|
+
The logical provider returns `advance`; a real shaped provider and matching font
|
|
195
|
+
realization remain later work.
|
|
196
|
+
|
|
197
|
+
Tate-chu-yoko retains the sum of member advances, including custom widths. The
|
|
198
|
+
composer does not silently rescale a custom measurement to one em. Negative or
|
|
199
|
+
non-finite advances and invalid cluster mappings produce a typed composition
|
|
200
|
+
failure rather than a partial layout.
|
|
179
201
|
|
|
180
202
|
Ruby annotations retain one of three associations: `group` for one reading over
|
|
181
203
|
the entire base, `mono` for one reading segment per base grapheme, and `jukugo`
|
|
@@ -206,7 +228,7 @@ ranges are distinct branded types, and plugin IDs are branded `NamespacedId`.
|
|
|
206
228
|
|
|
207
229
|
A companion object is exported as a value only when one of the three roles
|
|
208
230
|
calls something on it. Concepts you only ever read out of a composed layout —
|
|
209
|
-
`NovelPage`, `
|
|
231
|
+
`NovelPage`, `SingleGlyphUnit`, `CombinedGlyphUnit`, `LineBreakResult`, and the like — are exported as
|
|
210
232
|
types alone, so their schemas are not part of the API. The settings you persist
|
|
211
233
|
and re-validate keep theirs: `NovelCompositionSettings.schema`,
|
|
212
234
|
`ManuscriptAppearanceSettings.schema`, `ManuscriptOffsets.schema`,
|
|
@@ -218,12 +240,65 @@ failure carries exactly one error from a discriminated union, so callers can
|
|
|
218
240
|
as typed fields; `describe` renders one for display. Invalid settings and
|
|
219
241
|
plugin output fail explicitly; values are never clamped or partially trusted.
|
|
220
242
|
|
|
221
|
-
## Source mapping
|
|
243
|
+
## Source mapping and render units
|
|
222
244
|
|
|
223
245
|
Source and display ranges are zero-based, end-exclusive UTF-16 offsets.
|
|
224
|
-
Grapheme ranges index the normalized grapheme array.
|
|
225
|
-
|
|
226
|
-
|
|
246
|
+
Grapheme ranges index the normalized grapheme array. Measurement text ranges are
|
|
247
|
+
local to a request and have a different brand.
|
|
248
|
+
|
|
249
|
+
`NovelLine.items` contains `PositionedInlineItem`: single glyphs, combined glyphs,
|
|
250
|
+
glue, kern, and suppressed source text. Render units have distinct `layoutSpan`
|
|
251
|
+
and `renderSpan` values plus `sources`. An `exact` source placement locates one
|
|
252
|
+
parsed grapheme; a `shared` placement associates several graphemes with one span
|
|
253
|
+
without inventing interior caret positions. Default tate-chu-yoko retains exact
|
|
254
|
+
half-em positions for each digit. A diagnostic on a shared member highlights the
|
|
255
|
+
shared span while keeping the diagnostic's original range.
|
|
256
|
+
|
|
257
|
+
Hanging glyphs have zero layout advance and a nonzero render span. Authored glue
|
|
258
|
+
and suppressed separators keep their source ranges, including at line edges.
|
|
259
|
+
`NovelLine.range` includes all source-backed members. Generated spacing has no
|
|
260
|
+
source range.
|
|
261
|
+
|
|
262
|
+
Ruby fragments contain `readingItems`, each with a fragment-local `textRange`
|
|
263
|
+
and `AnnotationPlacement`. Emphasis fragments contain `placements`. Inline
|
|
264
|
+
positions are line-relative; block offsets start at the body's right edge and
|
|
265
|
+
increase leftward. The current right-side, half-size decorations use `side:
|
|
266
|
+
"before"`, `blockOffsetEm: -0.5`, and `blockSizeEm: 0.5`. The viewer consumes these
|
|
267
|
+
coordinates without computing ruby or emphasis placement.
|
|
268
|
+
|
|
269
|
+
Annotations retain their original logical association even on part of a combined
|
|
270
|
+
unit, whose whole physical span anchors the decoration. Incompatible readings on
|
|
271
|
+
members of the same unit cause a composition refusal. Bold and italic retain
|
|
272
|
+
source-range fragments. Ruby overhang depends on adjacent characters, resolved
|
|
273
|
+
punctuation spacing, and the candidate's line edges. Mono readings anchor to their
|
|
274
|
+
own bases; jukugo readings use solid shoulder placement and joint arrangement.
|
|
275
|
+
Jukugo placement tries compound-interior overhang before outside neighbours, then
|
|
276
|
+
distributes required spacing around long readings in proportion to their measured
|
|
277
|
+
widths. Line-edge shares go inward. A single-base fragment touching both edges
|
|
278
|
+
uses head alignment and box expansion when needed. Oversized group readings are
|
|
279
|
+
assigned as contiguous measurement-cluster intervals before line scoring.
|
|
280
|
+
|
|
281
|
+
Emphasis placements have a half-em inline extent centered on their render unit.
|
|
282
|
+
Brackets, commas, and full stops receive no marks. Ruby and nonempty emphasis
|
|
283
|
+
must fit the fixed half-em right-side area without colliding. Core may choose
|
|
284
|
+
another line break; an impossible combination returns `ComposerRejected` with
|
|
285
|
+
a reason. Body pitch, source ranges, and persisted settings remain unchanged.
|
|
286
|
+
Actual font shaping, selectable sides, sidelines, and mixed sizes remain deferred.
|
|
287
|
+
|
|
288
|
+
Diagnostics include one-based source line and column positions, so renderers do
|
|
289
|
+
not need to search or recalculate locations.
|
|
290
|
+
|
|
291
|
+
### Breaking API migration
|
|
292
|
+
|
|
293
|
+
Update core and viewer together. `SingleGlyphUnit`, `CombinedGlyphUnit`, and
|
|
294
|
+
`PositionedInlineItem` replace `ComposedGlyph` and `ComposedInlineItem`;
|
|
295
|
+
`PresentationKind` replaces the `VerticalTextPresentation` group object. The
|
|
296
|
+
plugin entry replaces `InlineMeasureRequest`, `InlineMeasurement`,
|
|
297
|
+
`InlineMeasurer`, and `logicalInlineMeasurer` with the run measurement contracts
|
|
298
|
+
above. `createNovelComposer({ measurer })` keeps its option name but requires the
|
|
299
|
+
new request and discriminated result. Ruby `readingGraphemes` becomes
|
|
300
|
+
`readingItems`; decoration positions move into core output. Persisted settings
|
|
301
|
+
and parser/proofreading entrypoints are unchanged.
|
|
227
302
|
|
|
228
303
|
## Proofreading rules
|
|
229
304
|
|