@sushichan044/kg-core 0.6.4 → 0.7.0

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 CHANGED
@@ -13,23 +13,38 @@ or DOM behavior.
13
13
  pnpm add @sushichan044/kg-core
14
14
  ```
15
15
 
16
+ ## Entry points
17
+
18
+ The package is split by what you are doing, so an application only ever sees the
19
+ surface it needs.
20
+
21
+ | Entry | For |
22
+ | ------------------------------ | ----------------------------------------------------------------------------------------------- |
23
+ | `@sushichan044/kg-core` | Running the pipeline and reading what comes out: parse, compose, settings, results, diagnostics |
24
+ | `@sushichan044/kg-core/lint` | Proofreading — running the rules, and writing your own |
25
+ | `@sushichan044/kg-core/plugin` | Supplying an implementation to core: a parser, a composer, or a measurer |
26
+
27
+ A name is exported only when one of those three needs to write it. Helpers core
28
+ keeps for itself are not part of the API.
29
+
16
30
  ## Processing pipeline
17
31
 
18
32
  ```ts
19
33
  import {
20
34
  ComposeError,
21
35
  composeManuscript,
22
- createNovelComposer,
23
- createDefaultProofreadingRules,
24
36
  NovelCompositionSettings,
25
37
  novelComposer,
26
38
  ParseError,
27
39
  parseManuscript,
28
40
  kakuyomuParser,
29
41
  pixivParser,
42
+ } from "@sushichan044/kg-core";
43
+ import {
44
+ createDefaultProofreadingRules,
30
45
  ProofreadError,
31
46
  proofreadManuscript,
32
- } from "@sushichan044/kg-core";
47
+ } from "@sushichan044/kg-core/lint";
33
48
 
34
49
  const parsed = parseManuscript(source, { parser: kakuyomuParser });
35
50
  if (!parsed.ok) throw new Error(ParseError.describe(parsed.error));
@@ -63,14 +78,29 @@ whether it ended naturally, by shrinking, stretching, hanging, forcing, or reach
63
78
  the paragraph end.
64
79
 
65
80
  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.
81
+ and selects line breaks over the whole source paragraph. The space between two
82
+ classes follows appendix 表1 of JLReq: a half em before an opening bracket and after
83
+ a closing bracket, comma, or full stop, a quarter em on either side of a middle dot,
84
+ a quarter em between Japanese and a numeral, unit symbol, or Western character, and
85
+ solid where two of those punctuation marks meet.
86
+
87
+ An overflowing line is answered by reducing that space or by hanging a comma or full
88
+ stop; a short line is answered by stretching eligible space; a line that admits none
89
+ of these is forced. The choice is made for the paragraph rather than line by line,
90
+ minimizing in order the number of forced lines, then stretched, then hanging, then
91
+ shrunk lines that spent visible space. Which space may be reduced, and in which
92
+ order, follows JLReq 3.8.3 and appendix 表3: the space at the line end goes first and
93
+ costs the paragraph nothing, because it is invisible once that character lands there;
94
+ then a middle dot's quarters, then the half em before an opening bracket or after a
95
+ closing bracket or comma, then the Japanese-to-Western quarter down to an eighth. The
96
+ half em after a mid-line full stop marks the end of a sentence and is never reduced,
97
+ and neither is the half em that keeps a line-head opening bracket off the edge.
98
+
99
+ The composer also owns Japanese line-start and line-end restrictions, inseparable
100
+ punctuation, question/exclamation gap suppression, and ruby placement.
71
101
 
72
102
  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),
103
+ [JLReq](https://www.w3.org/TR/jlreq/#mixed_text_composition_in_vertical_writing_mode),
74
104
  upright Latin initials and abbreviations advance by one em per character, Western
75
105
  words remain unbroken and render sideways, and two ASCII digits form one
76
106
  tate-chu-yoko unit. The resulting `VerticalTextPresentation` is carried by every
@@ -82,6 +112,8 @@ advance by half an em. Supply a synchronous measurer when the caller has more ac
82
112
  font metrics. Base-text requests also include the selected `presentation`:
83
113
 
84
114
  ```ts
115
+ import { createNovelComposer } from "@sushichan044/kg-core/plugin";
116
+
85
117
  const composer = createNovelComposer({
86
118
  measurer: (request) => ({
87
119
  advanceEm: measureWithAvailableFont(request.text, {
@@ -104,6 +136,10 @@ parser result with mismatched `mono` or `jukugo` segment counts is invalid.
104
136
 
105
137
  ## Extensions and validation
106
138
 
139
+ Everything in this section comes from `@sushichan044/kg-core/plugin`, except
140
+ proofreading rules, which are authored against `@sushichan044/kg-core/lint`
141
+ alongside the built-in ones.
142
+
107
143
  Parsers implement `ManuscriptParser`. Composers implement `ManuscriptComposer`
108
144
  and provide Valibot schemas for their settings and layout. Proofreading rules
109
145
  carry `kind: "parsed"` or `kind: "composed"` to declare which manuscript they
@@ -120,6 +156,14 @@ same name, holding its schema and operations: `ManuscriptRange.merge`,
120
156
  inferred from the schemas with `v.InferOutput`; source, display, and grapheme
121
157
  ranges are distinct branded types, and plugin IDs are branded `NamespacedId`.
122
158
 
159
+ A companion object is exported as a value only when one of the three roles
160
+ calls something on it. Concepts you only ever read out of a composed layout —
161
+ `NovelPage`, `ComposedGlyph`, `LineBreakResult`, and the like — are exported as
162
+ types alone, so their schemas are not part of the API. The settings you persist
163
+ and re-validate keep theirs: `NovelCompositionSettings.schema`,
164
+ `ManuscriptAppearanceSettings.schema`, `ManuscriptOffsets.schema`,
165
+ `NovelFlowSettings.schema`, and the appearance picklists.
166
+
123
167
  Processing functions return `ManuscriptResult`: success carries warnings, and
124
168
  failure carries exactly one error from a discriminated union, so callers can
125
169
  `switch` on `error.kind` exhaustively. Each error variant exposes its context
@@ -135,6 +179,10 @@ or recalculate locations.
135
179
 
136
180
  ## Proofreading rules
137
181
 
182
+ Proofreading has its own entry point, `@sushichan044/kg-core/lint`. Nothing in
183
+ the root entry imports from it, so an application that only parses and composes
184
+ never pulls the rules into its bundle.
185
+
138
186
  `createDefaultProofreadingRules()` returns the rules whose answer does not
139
187
  depend on the work: how a paragraph opens and how far it is indented,
140
188
  punctuation before a closing bracket, spacing after `!` and `?`, ellipsis and
@@ -152,7 +200,7 @@ import {
152
200
  consistentNumeralWidthRule,
153
201
  createConsistentKanjiOpeningRule,
154
202
  createDefaultProofreadingRules,
155
- } from "@sushichan044/kg-core";
203
+ } from "@sushichan044/kg-core/lint";
156
204
 
157
205
  const rules = [
158
206
  ...createDefaultProofreadingRules(),