@sushichan044/kg-core 0.6.2 → 0.6.4

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 (4) hide show
  1. package/README.md +54 -10
  2. package/dist/index.d.mts +24947 -6873
  3. package/dist/index.mjs +1126 -198
  4. package/package.json +3 -2
package/README.md CHANGED
@@ -19,9 +19,10 @@ pnpm add @sushichan044/kg-core
19
19
  import {
20
20
  ComposeError,
21
21
  composeManuscript,
22
+ createNovelComposer,
22
23
  createDefaultProofreadingRules,
23
- ManuscriptCompositionSettings,
24
- manuscriptGridComposer,
24
+ NovelCompositionSettings,
25
+ novelComposer,
25
26
  ParseError,
26
27
  parseManuscript,
27
28
  kakuyomuParser,
@@ -34,8 +35,8 @@ const parsed = parseManuscript(source, { parser: kakuyomuParser });
34
35
  if (!parsed.ok) throw new Error(ParseError.describe(parsed.error));
35
36
 
36
37
  const composed = composeManuscript(parsed.value, {
37
- composer: manuscriptGridComposer,
38
- settings: ManuscriptCompositionSettings.defaults,
38
+ composer: novelComposer,
39
+ settings: NovelCompositionSettings.defaults,
39
40
  });
40
41
  if (!composed.ok) throw new Error(ComposeError.describe(composed.error));
41
42
 
@@ -52,11 +53,54 @@ const diagnostics = [...parsed.warnings, ...proofread.value];
52
53
  normalizes Kakuyomu ruby and emphasis marks. Malformed or unknown notation remains
53
54
  visible and produces a parser warning.
54
55
 
55
- `composeManuscript` requires a composer. The built-in grid composer produces a
56
- self-contained snapshot containing the parsed manuscript, accepted settings,
57
- geometry, statistics, and page/stage/line/cell hierarchy. Every occupied
58
- element has source, display, and grapheme ranges; empty placement elements use
59
- `null`.
56
+ `composeManuscript` requires a composer. The built-in `novelComposer` produces
57
+ a self-contained snapshot containing the parsed manuscript, accepted settings,
58
+ geometry, statistics, and a page/stage/line hierarchy. Lines contain positioned
59
+ inline items and annotation fragments. `glyph` items distinguish their typographic
60
+ `layoutSpan` from their visual `renderSpan`; `glue`, `kern`, and `suppressed` items
61
+ preserve every spacing decision. Each line also records its `inlineSizeEm` and
62
+ whether it ended naturally, by shrinking, stretching, hanging, forcing, or reaching
63
+ the paragraph end.
64
+
65
+ The composer classifies the core prose classes from JLReq, resolves pair spacing,
66
+ and selects line breaks over the whole source paragraph. It prefers natural setting,
67
+ then shrinking punctuation space, hanging a comma or full stop, stretching eligible
68
+ space, and finally a forced emergency line. It owns Japanese line-start and line-end
69
+ restrictions, inseparable punctuation, question/exclamation gap suppression, and
70
+ ruby placement.
71
+
72
+ The composer classifies vertical text before measuring and breaking lines. Following
73
+ [JLReq](https://www.w3.org/TR/jlreq/#handling_of_western_text_in_vertical_writing),
74
+ upright Latin initials and abbreviations advance by one em per character, Western
75
+ words remain unbroken and render sideways, and two ASCII digits form one
76
+ tate-chu-yoko unit. The resulting `VerticalTextPresentation` is carried by every
77
+ glyph item, so renderers do not need to infer orientation independently.
78
+
79
+ The default logical measurer uses East Asian Width in a Japanese context. Upright
80
+ ASCII advances by one em; proportional ASCII and the members of a tate-chu-yoko unit
81
+ advance by half an em. Supply a synchronous measurer when the caller has more accurate
82
+ font metrics. Base-text requests also include the selected `presentation`:
83
+
84
+ ```ts
85
+ const composer = createNovelComposer({
86
+ measurer: (request) => ({
87
+ advanceEm: measureWithAvailableFont(request.text, {
88
+ role: request.role,
89
+ fontPreset: request.fontPreset,
90
+ writingMode: request.writingMode,
91
+ ...(request.role === "base" ? { presentation: request.presentation } : {}),
92
+ }),
93
+ }),
94
+ });
95
+ ```
96
+
97
+ A measurer returns `{ advanceEm }` in logical em units. Negative or non-finite
98
+ results reject the composition instead of producing a partial layout.
99
+
100
+ Ruby annotations retain one of three associations: `group` for one reading over
101
+ the entire base, `mono` for one reading segment per base grapheme, and `jukugo`
102
+ for a compound whose segments remain associated with each base grapheme. A
103
+ parser result with mismatched `mono` or `jukugo` segment counts is invalid.
60
104
 
61
105
  ## Extensions and validation
62
106
 
@@ -72,7 +116,7 @@ construct core's error types.
72
116
 
73
117
  Each concept lives in its own module as a type plus a companion object of the
74
118
  same name, holding its schema and operations: `ManuscriptRange.merge`,
75
- `PaperSize.of`, `ManuscriptCompositionSettings.defaults`, and so on. Types are
119
+ `PaperSize.of`, `NovelCompositionSettings.defaults`, and so on. Types are
76
120
  inferred from the schemas with `v.InferOutput`; source, display, and grapheme
77
121
  ranges are distinct branded types, and plugin IDs are branded `NamespacedId`.
78
122