@sushichan044/kg-core 0.4.1 → 0.5.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 +36 -4
- package/dist/index.d.mts +67 -6
- package/dist/index.mjs +358 -35
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -63,7 +63,8 @@ element has source, display, and grapheme ranges; empty placement elements use
|
|
|
63
63
|
Parsers implement `ManuscriptParser`. Composers implement `ManuscriptComposer`
|
|
64
64
|
and provide Valibot schemas for their settings and layout. Proofreading rules
|
|
65
65
|
carry `kind: "parsed"` or `kind: "composed"` to declare which manuscript they
|
|
66
|
-
need, and report findings through `context.report`.
|
|
66
|
+
need, and report findings through `context.report`. A report may name a
|
|
67
|
+
`severity`; omitting it means `error`.
|
|
67
68
|
|
|
68
69
|
A plugin signals its own failure with a `Rejection` — a plain reason string.
|
|
69
70
|
Core turns that into a variant of the stage's error union, so plugins never
|
|
@@ -88,9 +89,40 @@ Grapheme ranges index the normalized grapheme array. Diagnostics include
|
|
|
88
89
|
one-based source line and column positions, so renderers do not need to search
|
|
89
90
|
or recalculate locations.
|
|
90
91
|
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
92
|
+
## Proofreading rules
|
|
93
|
+
|
|
94
|
+
`createDefaultProofreadingRules()` returns the rules whose answer does not
|
|
95
|
+
depend on the work: how a paragraph opens and how far it is indented,
|
|
96
|
+
punctuation before a closing bracket, spacing after `!` and `?`, ellipsis and
|
|
97
|
+
dash forms and counts, repeated punctuation, repeated interpuncts and choonpu, a
|
|
98
|
+
minus sign that no number follows, halfwidth Japanese punctuation, Arabic
|
|
99
|
+
numeral length, and Unicode variation sequences.
|
|
100
|
+
|
|
101
|
+
Rules that depend on the work's own conventions are exported individually and
|
|
102
|
+
report `warning` instead of `error`, so a caller opts into them:
|
|
103
|
+
|
|
104
|
+
```ts
|
|
105
|
+
import {
|
|
106
|
+
consistentKanjiOpeningRule,
|
|
107
|
+
consistentLatinWidthRule,
|
|
108
|
+
consistentNumeralWidthRule,
|
|
109
|
+
createConsistentKanjiOpeningRule,
|
|
110
|
+
createDefaultProofreadingRules,
|
|
111
|
+
} from "@sushichan044/kg-core";
|
|
112
|
+
|
|
113
|
+
const rules = [
|
|
114
|
+
...createDefaultProofreadingRules(),
|
|
115
|
+
consistentNumeralWidthRule(),
|
|
116
|
+
consistentLatinWidthRule(),
|
|
117
|
+
consistentKanjiOpeningRule(),
|
|
118
|
+
];
|
|
119
|
+
```
|
|
120
|
+
|
|
121
|
+
`createConsistentKanjiOpeningRule({ pairs })` replaces the built-in kanji and
|
|
122
|
+
kana pairs; like every configurable rule it returns a `ManuscriptResult` and
|
|
123
|
+
fails with `InvalidRuleOptions` rather than dropping bad options.
|
|
124
|
+
|
|
125
|
+
Diagnostics do not modify the source and do not contain automatic fixes.
|
|
94
126
|
|
|
95
127
|
## Browser support
|
|
96
128
|
|
package/dist/index.d.mts
CHANGED
|
@@ -14432,6 +14432,10 @@ declare const ProofreadingReportSchema: v.SchemaWithPipe<readonly [v.StrictObjec
|
|
|
14432
14432
|
readonly data: v.OptionalSchema<v.SchemaWithPipe<readonly [v.RecordSchema<v.StringSchema<undefined>, v.UnionSchema<[v.StringSchema<undefined>, v.NumberSchema<undefined>], undefined>, undefined>, v.ReadonlyAction<{
|
|
14433
14433
|
[x: string]: string | number;
|
|
14434
14434
|
}>]>, undefined>;
|
|
14435
|
+
/**
|
|
14436
|
+
* Omitted means `error`: a rule that says nothing is claiming it found a real defect.
|
|
14437
|
+
*/
|
|
14438
|
+
readonly severity: v.OptionalSchema<v.PicklistSchema<["warning", "error"], undefined>, undefined>;
|
|
14435
14439
|
}, undefined>, v.ReadonlyAction<{
|
|
14436
14440
|
readonly range: Readonly<{
|
|
14437
14441
|
source: Readonly<{
|
|
@@ -14451,6 +14455,7 @@ declare const ProofreadingReportSchema: v.SchemaWithPipe<readonly [v.StrictObjec
|
|
|
14451
14455
|
data?: Readonly<{
|
|
14452
14456
|
[x: string]: string | number;
|
|
14453
14457
|
}> | undefined;
|
|
14458
|
+
severity?: "error" | "warning" | undefined;
|
|
14454
14459
|
}>]>;
|
|
14455
14460
|
/**
|
|
14456
14461
|
* What a rule hands back for one finding. The rule names a message it declared rather than
|
|
@@ -14517,6 +14522,10 @@ declare const ProofreadingReport: {
|
|
|
14517
14522
|
readonly data: v.OptionalSchema<v.SchemaWithPipe<readonly [v.RecordSchema<v.StringSchema<undefined>, v.UnionSchema<[v.StringSchema<undefined>, v.NumberSchema<undefined>], undefined>, undefined>, v.ReadonlyAction<{
|
|
14518
14523
|
[x: string]: string | number;
|
|
14519
14524
|
}>]>, undefined>;
|
|
14525
|
+
/**
|
|
14526
|
+
* Omitted means `error`: a rule that says nothing is claiming it found a real defect.
|
|
14527
|
+
*/
|
|
14528
|
+
readonly severity: v.OptionalSchema<v.PicklistSchema<["warning", "error"], undefined>, undefined>;
|
|
14520
14529
|
}, undefined>, v.ReadonlyAction<{
|
|
14521
14530
|
readonly range: Readonly<{
|
|
14522
14531
|
source: Readonly<{
|
|
@@ -14536,6 +14545,7 @@ declare const ProofreadingReport: {
|
|
|
14536
14545
|
data?: Readonly<{
|
|
14537
14546
|
[x: string]: string | number;
|
|
14538
14547
|
}> | undefined;
|
|
14548
|
+
severity?: "error" | "warning" | undefined;
|
|
14539
14549
|
}>]>;
|
|
14540
14550
|
};
|
|
14541
14551
|
//#endregion
|
|
@@ -14620,19 +14630,66 @@ declare function proofreadManuscript(manuscript: ParsedManuscript, options: Proo
|
|
|
14620
14630
|
*/
|
|
14621
14631
|
declare function proofreadManuscript<TComposed extends ComposedManuscript>(manuscript: TComposed, options: ProofreadOptions<ParsedProofreadingRule | ComposedProofreadingRule<TComposed>>): ProofreadOutcome;
|
|
14622
14632
|
//#endregion
|
|
14633
|
+
//#region src/proofreading/rules/consistent-kanji-opening.d.ts
|
|
14634
|
+
declare const KanjiOpeningPairSchema: v.SchemaWithPipe<readonly [v.SchemaWithPipe<readonly [v.StrictObjectSchema<{
|
|
14635
|
+
readonly closed: v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.NonEmptyAction<string, undefined>]>;
|
|
14636
|
+
readonly opened: v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.NonEmptyAction<string, undefined>]>;
|
|
14637
|
+
}, undefined>, v.ReadonlyAction<{
|
|
14638
|
+
closed: string;
|
|
14639
|
+
opened: string;
|
|
14640
|
+
}>]>, v.CheckAction<Readonly<{
|
|
14641
|
+
closed: string;
|
|
14642
|
+
opened: string;
|
|
14643
|
+
}>, "a pair must hold two different spellings">]>;
|
|
14644
|
+
/**
|
|
14645
|
+
* A word written in kanji, paired with the kana form of the same word.
|
|
14646
|
+
*/
|
|
14647
|
+
type KanjiOpeningPair = v.InferOutput<typeof KanjiOpeningPairSchema>;
|
|
14648
|
+
type ConsistentKanjiOpeningOptions = Readonly<{
|
|
14649
|
+
pairs?: readonly KanjiOpeningPair[];
|
|
14650
|
+
}>;
|
|
14651
|
+
declare const consistentKanjiOpeningRule: () => ParsedProofreadingRule;
|
|
14652
|
+
declare function createConsistentKanjiOpeningRule(options?: ConsistentKanjiOpeningOptions): ManuscriptResult<ParsedProofreadingRule, InvalidRuleOptions>;
|
|
14653
|
+
//#endregion
|
|
14654
|
+
//#region src/proofreading/rules/consistent-latin-width.d.ts
|
|
14655
|
+
declare const consistentLatinWidthRule: () => ParsedProofreadingRule;
|
|
14656
|
+
//#endregion
|
|
14657
|
+
//#region src/proofreading/rules/consistent-numeral-width.d.ts
|
|
14658
|
+
declare const consistentNumeralWidthRule: () => ParsedProofreadingRule;
|
|
14659
|
+
//#endregion
|
|
14660
|
+
//#region src/proofreading/rules/dash-character.d.ts
|
|
14661
|
+
/**
|
|
14662
|
+
* Stand-ins for `―`. Repeated `ー` belongs to `kg/no-consecutive-choonpu` and `−` to
|
|
14663
|
+
* `kg/minus-before-number`, so neither is reported twice.
|
|
14664
|
+
*/
|
|
14665
|
+
declare const dashCharacterRule: () => ParsedProofreadingRule;
|
|
14666
|
+
//#endregion
|
|
14623
14667
|
//#region src/proofreading/rules/default-rules.d.ts
|
|
14624
14668
|
/**
|
|
14625
14669
|
* The built-in rule set at its default configuration. Infallible by construction: every rule is
|
|
14626
14670
|
* built from constants, so there is no options error for a caller to handle.
|
|
14671
|
+
*
|
|
14672
|
+
* Rules whose answer depends on the work's own conventions — which width numerals take, whether a
|
|
14673
|
+
* word is written in kanji or kana — are exported individually instead of included here.
|
|
14627
14674
|
*/
|
|
14628
14675
|
declare function createDefaultProofreadingRules(): readonly ParsedProofreadingRule[];
|
|
14629
14676
|
//#endregion
|
|
14677
|
+
//#region src/proofreading/rules/ellipsis-character.d.ts
|
|
14678
|
+
/**
|
|
14679
|
+
* Stand-ins for `…`. Runs of `。` and `・` are left to the rules that already count them, so one
|
|
14680
|
+
* substitute is never reported twice.
|
|
14681
|
+
*/
|
|
14682
|
+
declare const ellipsisCharacterRule: () => ParsedProofreadingRule;
|
|
14683
|
+
//#endregion
|
|
14630
14684
|
//#region src/proofreading/rules/even-dash.d.ts
|
|
14631
14685
|
declare const evenDashRule: () => ParsedProofreadingRule;
|
|
14632
14686
|
//#endregion
|
|
14633
14687
|
//#region src/proofreading/rules/even-ellipsis.d.ts
|
|
14634
14688
|
declare const evenEllipsisRule: () => ParsedProofreadingRule;
|
|
14635
14689
|
//#endregion
|
|
14690
|
+
//#region src/proofreading/rules/fullwidth-japanese-punctuation.d.ts
|
|
14691
|
+
declare const fullwidthJapanesePunctuationRule: () => ParsedProofreadingRule;
|
|
14692
|
+
//#endregion
|
|
14636
14693
|
//#region src/proofreading/rules/max-arabic-numeral-digits.d.ts
|
|
14637
14694
|
type MaxArabicNumeralDigitsOptions = Readonly<{
|
|
14638
14695
|
maxDigits?: number;
|
|
@@ -14652,17 +14709,21 @@ declare const noConsecutiveInterpunctRule: () => ParsedProofreadingRule;
|
|
|
14652
14709
|
//#region src/proofreading/rules/no-consecutive-punctuation.d.ts
|
|
14653
14710
|
declare const noConsecutivePunctuationRule: () => ParsedProofreadingRule;
|
|
14654
14711
|
//#endregion
|
|
14655
|
-
//#region src/proofreading/rules/paragraph-
|
|
14656
|
-
type
|
|
14657
|
-
|
|
14712
|
+
//#region src/proofreading/rules/paragraph-opening.d.ts
|
|
14713
|
+
type ParagraphOpeningOptions = Readonly<{
|
|
14714
|
+
openingBrackets?: string;
|
|
14658
14715
|
}>;
|
|
14659
|
-
declare const
|
|
14660
|
-
declare function
|
|
14716
|
+
declare const paragraphOpeningRule: () => ParsedProofreadingRule;
|
|
14717
|
+
declare function createParagraphOpeningRule(options?: ParagraphOpeningOptions): ManuscriptResult<ParsedProofreadingRule, InvalidRuleOptions>;
|
|
14661
14718
|
//#endregion
|
|
14662
14719
|
//#region src/proofreading/rules/punctuation-before-closing-quote.d.ts
|
|
14663
14720
|
declare const punctuationBeforeClosingQuoteRule: () => ParsedProofreadingRule;
|
|
14664
14721
|
//#endregion
|
|
14665
14722
|
//#region src/proofreading/rules/space-after-question-or-exclamation.d.ts
|
|
14723
|
+
/**
|
|
14724
|
+
* Checks the gap that follows every run of ! or ?. A run at the end of a line or right before a
|
|
14725
|
+
* closing bracket needs no gap; anywhere else it takes exactly one ideographic space.
|
|
14726
|
+
*/
|
|
14666
14727
|
declare const spaceAfterQuestionOrExclamationRule: () => ParsedProofreadingRule;
|
|
14667
14728
|
//#endregion
|
|
14668
14729
|
//#region src/proofreading/rules/variant-character.d.ts
|
|
@@ -14671,4 +14732,4 @@ declare const spaceAfterQuestionOrExclamationRule: () => ParsedProofreadingRule;
|
|
|
14671
14732
|
*/
|
|
14672
14733
|
declare const variantCharacterRule: () => ParsedProofreadingRule;
|
|
14673
14734
|
//#endregion
|
|
14674
|
-
export { BoldAnnotation, ComposeError, type ComposeManuscriptOptions, type ComposedManuscript, type ComposedProofreadingRule, CompositionStatistics, DiagnosticOrigin, DiagnosticSeverity, DisplayRange, EmphasisAnnotation, FontPreset, FontPresetId, FontSizePt, GraphemeRange, GridCell, type GridComposedManuscript, GridLine, GridPage, GridSettings, GridStage, InvalidRuleOptions, ItalicAnnotation, LineOffset, ManuscriptAnnotation, ManuscriptAppearanceSettings, type ManuscriptComposer, ManuscriptCompositionSettings, ManuscriptDiagnostic, type ManuscriptDiagnosticInput, ManuscriptGeometry, ManuscriptGridLayout, ManuscriptOffsets, type ManuscriptParser, ManuscriptRange, type ManuscriptRangeInput, ManuscriptResult, type MaxArabicNumeralDigitsOptions, NamespacedId, PaperSize, PaperSizeId, type
|
|
14735
|
+
export { BoldAnnotation, ComposeError, type ComposeManuscriptOptions, type ComposedManuscript, type ComposedProofreadingRule, CompositionStatistics, type ConsistentKanjiOpeningOptions, DiagnosticOrigin, DiagnosticSeverity, DisplayRange, EmphasisAnnotation, FontPreset, FontPresetId, FontSizePt, GraphemeRange, GridCell, type GridComposedManuscript, GridLine, GridPage, GridSettings, GridStage, InvalidRuleOptions, ItalicAnnotation, type KanjiOpeningPair, LineOffset, ManuscriptAnnotation, ManuscriptAppearanceSettings, type ManuscriptComposer, ManuscriptCompositionSettings, ManuscriptDiagnostic, type ManuscriptDiagnosticInput, ManuscriptGeometry, ManuscriptGridLayout, ManuscriptOffsets, type ManuscriptParser, ManuscriptRange, type ManuscriptRangeInput, ManuscriptResult, type MaxArabicNumeralDigitsOptions, NamespacedId, PaperSize, PaperSizeId, type ParagraphOpeningOptions, ParseError, type ParseManuscriptOptions, ParsedGrapheme, ParsedManuscript, type ParsedProofreadingRule, ProofreadError, type ProofreadOptions, ProofreadingReport, type ProofreadingRule, type ProofreadingRuleContext, type ProofreadingRuleMessages, ProofreadingRuleMeta, Rejection, RubyAnnotation, SourcePosition, SourceRange, TextRange, ValidationIssue, assertNever, composeManuscript, consistentKanjiOpeningRule, consistentLatinWidthRule, consistentNumeralWidthRule, createConsistentKanjiOpeningRule, createDefaultProofreadingRules, createMaxArabicNumeralDigitsRule, createParagraphOpeningRule, dashCharacterRule, ellipsisCharacterRule, evenDashRule, evenEllipsisRule, fullwidthJapanesePunctuationRule, kakuyomuParser, manuscriptGridComposer, maxArabicNumeralDigitsRule, minusBeforeNumberRule, mmToPt, noConsecutiveChoonpuRule, noConsecutiveInterpunctRule, noConsecutivePunctuationRule, paragraphOpeningRule, parseManuscript, pixivParser, plainTextParser, proofreadManuscript, ptToMm, punctuationBeforeClosingQuoteRule, spaceAfterQuestionOrExclamationRule, variantCharacterRule };
|
package/dist/index.mjs
CHANGED
|
@@ -1298,7 +1298,11 @@ function interpolate(template, data) {
|
|
|
1298
1298
|
const ProofreadingReport = { schema: readonlyObject({
|
|
1299
1299
|
range: ManuscriptRange.schema,
|
|
1300
1300
|
messageId: v.string(),
|
|
1301
|
-
data: v.optional(v.pipe(v.record(v.string(), v.union([v.string(), v.number()])), v.readonly()))
|
|
1301
|
+
data: v.optional(v.pipe(v.record(v.string(), v.union([v.string(), v.number()])), v.readonly())),
|
|
1302
|
+
/**
|
|
1303
|
+
* Omitted means `error`: a rule that says nothing is claiming it found a real defect.
|
|
1304
|
+
*/
|
|
1305
|
+
severity: v.optional(DiagnosticSeverity.schema)
|
|
1302
1306
|
}) };
|
|
1303
1307
|
//#endregion
|
|
1304
1308
|
//#region src/proofreading/proofreading-rule.ts
|
|
@@ -1389,7 +1393,7 @@ function toDiagnostics({ id, messages }, reports, source) {
|
|
|
1389
1393
|
kind: "rule",
|
|
1390
1394
|
id
|
|
1391
1395
|
},
|
|
1392
|
-
severity: "error",
|
|
1396
|
+
severity: report.severity ?? "error",
|
|
1393
1397
|
code: report.messageId,
|
|
1394
1398
|
message: interpolate(template, report.data),
|
|
1395
1399
|
range: report.range
|
|
@@ -1509,8 +1513,9 @@ function defineParsedRule(id, message, check) {
|
|
|
1509
1513
|
messages: { [DEFAULT_MESSAGE_ID]: message }
|
|
1510
1514
|
},
|
|
1511
1515
|
check: (manuscript, context) => {
|
|
1512
|
-
check(manuscript, (range) => {
|
|
1516
|
+
check(manuscript, (range, options) => {
|
|
1513
1517
|
context.report({
|
|
1518
|
+
...options,
|
|
1514
1519
|
range,
|
|
1515
1520
|
messageId: DEFAULT_MESSAGE_ID
|
|
1516
1521
|
});
|
|
@@ -1538,6 +1543,148 @@ function defineMatchRule(options) {
|
|
|
1538
1543
|
});
|
|
1539
1544
|
}
|
|
1540
1545
|
//#endregion
|
|
1546
|
+
//#region src/proofreading/rules/consistent-kanji-opening.ts
|
|
1547
|
+
const RULE_ID$4 = "kg/consistent-kanji-opening";
|
|
1548
|
+
const MESSAGE = "「{{ closed }}」と「{{ opened }}」が混在しています。文脈上の使い分けか表記ゆれかを確認してください";
|
|
1549
|
+
const KanjiOpeningPairSchema = v.pipe(readonlyObject({
|
|
1550
|
+
closed: v.pipe(v.string(), v.nonEmpty()),
|
|
1551
|
+
opened: v.pipe(v.string(), v.nonEmpty())
|
|
1552
|
+
}), v.check(({ closed, opened }) => closed !== opened, "a pair must hold two different spellings"));
|
|
1553
|
+
const PairsSchema = v.pipe(v.array(KanjiOpeningPairSchema), v.nonEmpty(), v.readonly());
|
|
1554
|
+
const DEFAULT_PAIRS = [
|
|
1555
|
+
{
|
|
1556
|
+
closed: "出来る",
|
|
1557
|
+
opened: "できる"
|
|
1558
|
+
},
|
|
1559
|
+
{
|
|
1560
|
+
closed: "出来ない",
|
|
1561
|
+
opened: "できない"
|
|
1562
|
+
},
|
|
1563
|
+
{
|
|
1564
|
+
closed: "下さい",
|
|
1565
|
+
opened: "ください"
|
|
1566
|
+
},
|
|
1567
|
+
{
|
|
1568
|
+
closed: "頂く",
|
|
1569
|
+
opened: "いただく"
|
|
1570
|
+
},
|
|
1571
|
+
{
|
|
1572
|
+
closed: "致す",
|
|
1573
|
+
opened: "いたす"
|
|
1574
|
+
},
|
|
1575
|
+
{
|
|
1576
|
+
closed: "何故",
|
|
1577
|
+
opened: "なぜ"
|
|
1578
|
+
},
|
|
1579
|
+
{
|
|
1580
|
+
closed: "為に",
|
|
1581
|
+
opened: "ために"
|
|
1582
|
+
},
|
|
1583
|
+
{
|
|
1584
|
+
closed: "時に",
|
|
1585
|
+
opened: "ときに"
|
|
1586
|
+
},
|
|
1587
|
+
{
|
|
1588
|
+
closed: "様に",
|
|
1589
|
+
opened: "ように"
|
|
1590
|
+
},
|
|
1591
|
+
{
|
|
1592
|
+
closed: "方が",
|
|
1593
|
+
opened: "ほうが"
|
|
1594
|
+
}
|
|
1595
|
+
];
|
|
1596
|
+
/**
|
|
1597
|
+
* Reports the first kanji occurrence of every pair the manuscript also writes in kana. Whether the
|
|
1598
|
+
* two spellings are a deliberate distinction is the author's call, so the finding is a warning.
|
|
1599
|
+
*/
|
|
1600
|
+
function build$2(pairs) {
|
|
1601
|
+
return defineParsedRule(RULE_ID$4, MESSAGE, (manuscript, report) => {
|
|
1602
|
+
for (const { closed, opened } of pairs) {
|
|
1603
|
+
if (!manuscript.displayText.includes(opened)) continue;
|
|
1604
|
+
const index = manuscript.displayText.indexOf(closed);
|
|
1605
|
+
if (index === -1) continue;
|
|
1606
|
+
report(displayRange(manuscript, index, index + closed.length), {
|
|
1607
|
+
data: {
|
|
1608
|
+
closed,
|
|
1609
|
+
opened
|
|
1610
|
+
},
|
|
1611
|
+
severity: "warning"
|
|
1612
|
+
});
|
|
1613
|
+
}
|
|
1614
|
+
});
|
|
1615
|
+
}
|
|
1616
|
+
const consistentKanjiOpeningRule = () => build$2(DEFAULT_PAIRS);
|
|
1617
|
+
function createConsistentKanjiOpeningRule(options = {}) {
|
|
1618
|
+
if (options.pairs === void 0) return ManuscriptResult.succeed(consistentKanjiOpeningRule());
|
|
1619
|
+
const pairs = v.safeParse(PairsSchema, options.pairs);
|
|
1620
|
+
if (!pairs.success) return ManuscriptResult.fail({
|
|
1621
|
+
kind: "InvalidRuleOptions",
|
|
1622
|
+
ruleId: RULE_ID$4,
|
|
1623
|
+
option: "pairs",
|
|
1624
|
+
issues: ValidationIssue.from(pairs.issues)
|
|
1625
|
+
});
|
|
1626
|
+
return ManuscriptResult.succeed(build$2(pairs.output));
|
|
1627
|
+
}
|
|
1628
|
+
//#endregion
|
|
1629
|
+
//#region src/proofreading/rules/internal/mixed-width.ts
|
|
1630
|
+
/**
|
|
1631
|
+
* Builds a rule that fires when a manuscript uses both widths of one character class. Which width
|
|
1632
|
+
* is right is the author's decision, so the finding is a warning, and one finding at the first
|
|
1633
|
+
* halfwidth occurrence says everything a list of every mixed character would.
|
|
1634
|
+
*/
|
|
1635
|
+
function defineMixedWidthRule({ id, message, halfwidth, fullwidth }) {
|
|
1636
|
+
return defineParsedRule(id, message, (manuscript, report) => {
|
|
1637
|
+
const found = halfwidth.exec(manuscript.displayText);
|
|
1638
|
+
const counterpart = fullwidth.exec(manuscript.displayText);
|
|
1639
|
+
if (found === null || counterpart === null) return;
|
|
1640
|
+
report(displayRange(manuscript, found.index, found.index + found[0].length), {
|
|
1641
|
+
data: {
|
|
1642
|
+
halfwidth: found[0],
|
|
1643
|
+
fullwidth: counterpart[0]
|
|
1644
|
+
},
|
|
1645
|
+
severity: "warning"
|
|
1646
|
+
});
|
|
1647
|
+
});
|
|
1648
|
+
}
|
|
1649
|
+
//#endregion
|
|
1650
|
+
//#region src/proofreading/rules/consistent-latin-width.ts
|
|
1651
|
+
const consistentLatinWidthRule = () => defineMixedWidthRule({
|
|
1652
|
+
id: "kg/consistent-latin-width",
|
|
1653
|
+
message: "半角英字「{{ halfwidth }}」と全角英字「{{ fullwidth }}」が混在しています。作品内の方針を確認してください",
|
|
1654
|
+
halfwidth: /[A-Za-z]/u,
|
|
1655
|
+
fullwidth: /[A-Za-z]/u
|
|
1656
|
+
});
|
|
1657
|
+
//#endregion
|
|
1658
|
+
//#region src/proofreading/rules/consistent-numeral-width.ts
|
|
1659
|
+
const consistentNumeralWidthRule = () => defineMixedWidthRule({
|
|
1660
|
+
id: "kg/consistent-numeral-width",
|
|
1661
|
+
message: "半角数字「{{ halfwidth }}」と全角数字「{{ fullwidth }}」が混在しています。作品内の方針を確認してください",
|
|
1662
|
+
halfwidth: /[0-9]/u,
|
|
1663
|
+
fullwidth: /[0-9]/u
|
|
1664
|
+
});
|
|
1665
|
+
//#endregion
|
|
1666
|
+
//#region src/proofreading/rules/dash-character.ts
|
|
1667
|
+
/**
|
|
1668
|
+
* Stand-ins for `―`. Repeated `ー` belongs to `kg/no-consecutive-choonpu` and `−` to
|
|
1669
|
+
* `kg/minus-before-number`, so neither is reported twice.
|
|
1670
|
+
*/
|
|
1671
|
+
const dashCharacterRule = () => defineMatchRule({
|
|
1672
|
+
id: "kg/dash-character",
|
|
1673
|
+
pattern: /[—–─━﹣-]+|-{2,}/gu,
|
|
1674
|
+
message: "ダッシュには「―」を使ってください"
|
|
1675
|
+
});
|
|
1676
|
+
//#endregion
|
|
1677
|
+
//#region src/proofreading/rules/ellipsis-character.ts
|
|
1678
|
+
/**
|
|
1679
|
+
* Stand-ins for `…`. Runs of `。` and `・` are left to the rules that already count them, so one
|
|
1680
|
+
* substitute is never reported twice.
|
|
1681
|
+
*/
|
|
1682
|
+
const ellipsisCharacterRule = () => defineMatchRule({
|
|
1683
|
+
id: "kg/ellipsis-character",
|
|
1684
|
+
pattern: /\.{3,}|⋯+/gu,
|
|
1685
|
+
message: "三点リーダーには「…」を使ってください"
|
|
1686
|
+
});
|
|
1687
|
+
//#endregion
|
|
1541
1688
|
//#region src/proofreading/rules/even-dash.ts
|
|
1542
1689
|
const evenDashRule = () => defineMatchRule({
|
|
1543
1690
|
id: "kg/even-dash",
|
|
@@ -1554,13 +1701,78 @@ const evenEllipsisRule = () => defineMatchRule({
|
|
|
1554
1701
|
message: "連続する三点リーダーの数は偶数にしてください"
|
|
1555
1702
|
});
|
|
1556
1703
|
//#endregion
|
|
1704
|
+
//#region src/proofreading/rules/fullwidth-japanese-punctuation.ts
|
|
1705
|
+
const RULE_ID$3 = "kg/fullwidth-japanese-punctuation";
|
|
1706
|
+
const MESSAGES$2 = {
|
|
1707
|
+
"halfwidth-japanese-punctuation": "半角の「{{ character }}」があります。日本語の句読点・括弧・感嘆符・疑問符は全角にしてください",
|
|
1708
|
+
"halfwidth-near-japanese": "日本語の前後に半角の「{{ character }}」があります。全角にすべきか確認してください"
|
|
1709
|
+
};
|
|
1710
|
+
const JAPANESE_CHARACTER = /[\p{Script=Han}\p{Script=Hiragana}\p{Script=Katakana}々〆ヵヶ]/u;
|
|
1711
|
+
const CHECKS = [
|
|
1712
|
+
{
|
|
1713
|
+
pattern: /[。、「」]/gu,
|
|
1714
|
+
messageId: "halfwidth-japanese-punctuation",
|
|
1715
|
+
severity: "error",
|
|
1716
|
+
requiresJapanese: false
|
|
1717
|
+
},
|
|
1718
|
+
{
|
|
1719
|
+
pattern: /[!?]/gu,
|
|
1720
|
+
messageId: "halfwidth-japanese-punctuation",
|
|
1721
|
+
severity: "error",
|
|
1722
|
+
requiresJapanese: true
|
|
1723
|
+
},
|
|
1724
|
+
{
|
|
1725
|
+
pattern: /[,.()[\]{}]/gu,
|
|
1726
|
+
messageId: "halfwidth-near-japanese",
|
|
1727
|
+
severity: "warning",
|
|
1728
|
+
requiresJapanese: true
|
|
1729
|
+
}
|
|
1730
|
+
];
|
|
1731
|
+
function isBesideJapanese(text, index) {
|
|
1732
|
+
const before = text[index - 1];
|
|
1733
|
+
const after = text[index + 1];
|
|
1734
|
+
return before !== void 0 && JAPANESE_CHARACTER.test(before) || after !== void 0 && JAPANESE_CHARACTER.test(after);
|
|
1735
|
+
}
|
|
1736
|
+
/**
|
|
1737
|
+
* A period inside a run of three or more is a stand-in for `…`, which `kg/ellipsis-character`
|
|
1738
|
+
* already reports.
|
|
1739
|
+
*/
|
|
1740
|
+
function isEllipsisSubstitute(text, index) {
|
|
1741
|
+
if (text[index] !== ".") return false;
|
|
1742
|
+
let start = index;
|
|
1743
|
+
while (text[start - 1] === ".") start -= 1;
|
|
1744
|
+
let end = index;
|
|
1745
|
+
while (text[end + 1] === ".") end += 1;
|
|
1746
|
+
return end - start + 1 >= 3;
|
|
1747
|
+
}
|
|
1748
|
+
const fullwidthJapanesePunctuationRule = () => ({
|
|
1749
|
+
kind: "parsed",
|
|
1750
|
+
meta: {
|
|
1751
|
+
id: RULE_ID$3,
|
|
1752
|
+
messages: MESSAGES$2
|
|
1753
|
+
},
|
|
1754
|
+
check: (manuscript, context) => {
|
|
1755
|
+
for (const line of splitDisplayLines(manuscript.displayText)) for (const { pattern, messageId, severity, requiresJapanese } of CHECKS) for (const match of line.text.matchAll(pattern)) {
|
|
1756
|
+
if (requiresJapanese && !isBesideJapanese(line.text, match.index)) continue;
|
|
1757
|
+
if (isEllipsisSubstitute(line.text, match.index)) continue;
|
|
1758
|
+
const start = line.start + match.index;
|
|
1759
|
+
context.report({
|
|
1760
|
+
range: displayRange(manuscript, start, start + match[0].length),
|
|
1761
|
+
messageId,
|
|
1762
|
+
data: { character: match[0] },
|
|
1763
|
+
severity
|
|
1764
|
+
});
|
|
1765
|
+
}
|
|
1766
|
+
}
|
|
1767
|
+
});
|
|
1768
|
+
//#endregion
|
|
1557
1769
|
//#region src/proofreading/rules/max-arabic-numeral-digits.ts
|
|
1558
|
-
const RULE_ID$
|
|
1770
|
+
const RULE_ID$2 = "kg/max-arabic-numeral-digits";
|
|
1559
1771
|
const DEFAULT_MAX_DIGITS = 2;
|
|
1560
1772
|
const MaxDigitsSchema = v.pipe(v.number(), v.finite(), v.integer(), v.minValue(1));
|
|
1561
1773
|
function build$1(maxDigits) {
|
|
1562
1774
|
return defineMatchRule({
|
|
1563
|
-
id: RULE_ID$
|
|
1775
|
+
id: RULE_ID$2,
|
|
1564
1776
|
pattern: /([0-90-9]+)(?:[..]([0-90-9]+))?/gu,
|
|
1565
1777
|
accept: (match) => (match[1]?.length ?? 0) > maxDigits || (match[2]?.length ?? 0) > maxDigits,
|
|
1566
1778
|
message: `${maxDigits}桁を超えるアラビア数字が使われています`
|
|
@@ -1572,7 +1784,7 @@ function createMaxArabicNumeralDigitsRule(options = {}) {
|
|
|
1572
1784
|
const maxDigits = v.safeParse(MaxDigitsSchema, options.maxDigits);
|
|
1573
1785
|
if (!maxDigits.success) return ManuscriptResult.fail({
|
|
1574
1786
|
kind: "InvalidRuleOptions",
|
|
1575
|
-
ruleId: RULE_ID$
|
|
1787
|
+
ruleId: RULE_ID$2,
|
|
1576
1788
|
option: "maxDigits",
|
|
1577
1789
|
issues: ValidationIssue.from(maxDigits.issues)
|
|
1578
1790
|
});
|
|
@@ -1607,46 +1819,151 @@ const noConsecutivePunctuationRule = () => defineMatchRule({
|
|
|
1607
1819
|
message: "句読点が連続しています"
|
|
1608
1820
|
});
|
|
1609
1821
|
//#endregion
|
|
1610
|
-
//#region src/proofreading/rules/
|
|
1611
|
-
|
|
1612
|
-
|
|
1613
|
-
|
|
1614
|
-
|
|
1615
|
-
|
|
1616
|
-
|
|
1617
|
-
|
|
1618
|
-
|
|
1619
|
-
|
|
1620
|
-
|
|
1621
|
-
|
|
1822
|
+
//#region src/proofreading/rules/internal/brackets.ts
|
|
1823
|
+
/**
|
|
1824
|
+
* Brackets and quotes a Japanese paragraph may open with. Halfwidth forms are included because a
|
|
1825
|
+
* manuscript that uses them is still opening a paragraph, not writing prose.
|
|
1826
|
+
*/
|
|
1827
|
+
const OPENING_BRACKETS = "「『〖〈《((“\"‘'[[〔{{<<";
|
|
1828
|
+
/**
|
|
1829
|
+
* The closing counterparts, in the same order.
|
|
1830
|
+
*/
|
|
1831
|
+
const CLOSING_BRACKETS = "」』〗〉》))”\"’']]〕}}>>";
|
|
1832
|
+
/**
|
|
1833
|
+
* Escapes the characters a regular expression character class would otherwise read as syntax, so a
|
|
1834
|
+
* set declared above can be dropped into a pattern.
|
|
1835
|
+
*/
|
|
1836
|
+
function characterClass(characters) {
|
|
1837
|
+
return characters.replaceAll(/[\\\]^-]/gu, "\\$&");
|
|
1838
|
+
}
|
|
1839
|
+
//#endregion
|
|
1840
|
+
//#region src/proofreading/rules/internal/decoration-line.ts
|
|
1841
|
+
const DECORATION_LINE = /^[**◆◇■□●○▽▼△▲☆★・…―─━ー\-==~~\s]+$/u;
|
|
1842
|
+
/**
|
|
1843
|
+
* A line made only of symbols and spaces: a scene break or a section marker rather than a
|
|
1844
|
+
* paragraph. Indentation rules skip these, because their layout is deliberate.
|
|
1845
|
+
*/
|
|
1846
|
+
function isDecorationLine(text) {
|
|
1847
|
+
return DECORATION_LINE.test(text);
|
|
1848
|
+
}
|
|
1849
|
+
//#endregion
|
|
1850
|
+
//#region src/proofreading/rules/internal/spaces.ts
|
|
1851
|
+
const LEADING_SPACES = /^[ \t]+/u;
|
|
1852
|
+
/**
|
|
1853
|
+
* The run of spaces the text begins with, or an empty string. Halfwidth spaces and tabs count: a
|
|
1854
|
+
* rule has to see them to say they are the wrong space.
|
|
1855
|
+
*/
|
|
1856
|
+
function leadingSpaces(text) {
|
|
1857
|
+
return LEADING_SPACES.exec(text)?.[0] ?? "";
|
|
1858
|
+
}
|
|
1859
|
+
//#endregion
|
|
1860
|
+
//#region src/proofreading/rules/paragraph-opening.ts
|
|
1861
|
+
const RULE_ID$1 = "kg/paragraph-opening";
|
|
1862
|
+
const MESSAGES$1 = {
|
|
1863
|
+
"leading-character": "段落の先頭には全角スペースまたは開き括弧が必要です",
|
|
1864
|
+
"indent-width": "段落冒頭の字下げは全角スペース1字にしてください",
|
|
1865
|
+
"unexpected-indent": "括弧から始まる段落を字下げすることはできません"
|
|
1866
|
+
};
|
|
1867
|
+
const OpeningBracketsSchema = v.pipe(v.string(), v.nonEmpty());
|
|
1868
|
+
/**
|
|
1869
|
+
* How a paragraph opens, judged as one decision: a paragraph that opens with a bracket carries no
|
|
1870
|
+
* indent, and prose carries exactly one ideographic space. The three findings are branches of that
|
|
1871
|
+
* one decision rather than separate rules, so a line can never collect two of them at once.
|
|
1872
|
+
*/
|
|
1873
|
+
function build(openingBrackets) {
|
|
1874
|
+
return {
|
|
1875
|
+
kind: "parsed",
|
|
1876
|
+
meta: {
|
|
1877
|
+
id: RULE_ID$1,
|
|
1878
|
+
messages: MESSAGES$1
|
|
1879
|
+
},
|
|
1880
|
+
check: (manuscript, context) => {
|
|
1881
|
+
const report = (start, end, messageId) => {
|
|
1882
|
+
context.report({
|
|
1883
|
+
range: displayRange(manuscript, start, end),
|
|
1884
|
+
messageId
|
|
1885
|
+
});
|
|
1886
|
+
};
|
|
1887
|
+
for (const line of splitDisplayLines(manuscript.displayText)) {
|
|
1888
|
+
if (isDecorationLine(line.text)) continue;
|
|
1889
|
+
const indent = leadingSpaces(line.text);
|
|
1890
|
+
const opening = line.text[indent.length];
|
|
1891
|
+
if (opening === void 0) continue;
|
|
1892
|
+
if (openingBrackets.includes(opening)) {
|
|
1893
|
+
if (indent !== "") report(line.start, line.start + indent.length, "unexpected-indent");
|
|
1894
|
+
} else if (!line.text.startsWith(" ")) {
|
|
1895
|
+
const length = (line.text.codePointAt(0) ?? 0) > 65535 ? 2 : 1;
|
|
1896
|
+
report(line.start, line.start + length, "leading-character");
|
|
1897
|
+
} else if (indent.length !== 1) report(line.start, line.start + indent.length, "indent-width");
|
|
1898
|
+
}
|
|
1622
1899
|
}
|
|
1623
|
-
}
|
|
1900
|
+
};
|
|
1624
1901
|
}
|
|
1625
|
-
const
|
|
1626
|
-
function
|
|
1627
|
-
if (options.
|
|
1628
|
-
const
|
|
1629
|
-
if (!
|
|
1902
|
+
const paragraphOpeningRule = () => build(OPENING_BRACKETS);
|
|
1903
|
+
function createParagraphOpeningRule(options = {}) {
|
|
1904
|
+
if (options.openingBrackets === void 0) return ManuscriptResult.succeed(paragraphOpeningRule());
|
|
1905
|
+
const brackets = v.safeParse(OpeningBracketsSchema, options.openingBrackets);
|
|
1906
|
+
if (!brackets.success) return ManuscriptResult.fail({
|
|
1630
1907
|
kind: "InvalidRuleOptions",
|
|
1631
|
-
ruleId: RULE_ID,
|
|
1632
|
-
option: "
|
|
1633
|
-
issues: ValidationIssue.from(
|
|
1908
|
+
ruleId: RULE_ID$1,
|
|
1909
|
+
option: "openingBrackets",
|
|
1910
|
+
issues: ValidationIssue.from(brackets.issues)
|
|
1634
1911
|
});
|
|
1635
|
-
return ManuscriptResult.succeed(build(
|
|
1912
|
+
return ManuscriptResult.succeed(build(brackets.output));
|
|
1636
1913
|
}
|
|
1637
1914
|
//#endregion
|
|
1638
1915
|
//#region src/proofreading/rules/punctuation-before-closing-quote.ts
|
|
1916
|
+
const PATTERN = new RegExp(`[。、]+(?=[${characterClass(CLOSING_BRACKETS)}])`, "gu");
|
|
1639
1917
|
const punctuationBeforeClosingQuoteRule = () => defineMatchRule({
|
|
1640
1918
|
id: "kg/punctuation-before-closing-quote",
|
|
1641
|
-
pattern:
|
|
1919
|
+
pattern: PATTERN,
|
|
1642
1920
|
message: "閉じ括弧の直前に句読点を置くことはできません"
|
|
1643
1921
|
});
|
|
1644
1922
|
//#endregion
|
|
1645
1923
|
//#region src/proofreading/rules/space-after-question-or-exclamation.ts
|
|
1646
|
-
const
|
|
1647
|
-
|
|
1648
|
-
|
|
1649
|
-
|
|
1924
|
+
const RULE_ID = "kg/space-after-question-or-exclamation";
|
|
1925
|
+
const MESSAGES = {
|
|
1926
|
+
default: "感嘆符または疑問符の直後には全角スペースか閉じ括弧が必要です",
|
|
1927
|
+
"space-width": "感嘆符または疑問符の直後の空白は全角スペース1字にしてください",
|
|
1928
|
+
"before-closing-bracket": "閉じ括弧の直前に空白を置くことはできません"
|
|
1929
|
+
};
|
|
1930
|
+
/**
|
|
1931
|
+
* Runs, not single marks: `!?` is one mark and takes one gap, so the gap belongs after the run.
|
|
1932
|
+
*/
|
|
1933
|
+
const MARKS = /[?!]+/gu;
|
|
1934
|
+
/**
|
|
1935
|
+
* Checks the gap that follows every run of ! or ?. A run at the end of a line or right before a
|
|
1936
|
+
* closing bracket needs no gap; anywhere else it takes exactly one ideographic space.
|
|
1937
|
+
*/
|
|
1938
|
+
const spaceAfterQuestionOrExclamationRule = () => ({
|
|
1939
|
+
kind: "parsed",
|
|
1940
|
+
meta: {
|
|
1941
|
+
id: RULE_ID,
|
|
1942
|
+
messages: MESSAGES
|
|
1943
|
+
},
|
|
1944
|
+
check: (manuscript, context) => {
|
|
1945
|
+
const report = (start, end, messageId) => {
|
|
1946
|
+
context.report({
|
|
1947
|
+
range: displayRange(manuscript, start, end),
|
|
1948
|
+
messageId
|
|
1949
|
+
});
|
|
1950
|
+
};
|
|
1951
|
+
for (const line of splitDisplayLines(manuscript.displayText)) for (const marks of line.text.matchAll(MARKS)) {
|
|
1952
|
+
const marksEnd = marks.index + marks[0].length;
|
|
1953
|
+
const next = line.text[marksEnd];
|
|
1954
|
+
if (next === void 0 || "」』〗〉》))”\"’']]〕}}>>".includes(next)) continue;
|
|
1955
|
+
const spaces = leadingSpaces(line.text.slice(marksEnd));
|
|
1956
|
+
if (spaces === "") {
|
|
1957
|
+
report(line.start + marks.index, line.start + marksEnd, "default");
|
|
1958
|
+
continue;
|
|
1959
|
+
}
|
|
1960
|
+
const following = line.text[marksEnd + spaces.length];
|
|
1961
|
+
const spacesStart = line.start + marksEnd;
|
|
1962
|
+
const spacesEnd = spacesStart + spaces.length;
|
|
1963
|
+
if (following !== void 0 && "」』〗〉》))”\"’']]〕}}>>".includes(following)) report(spacesStart, spacesEnd, "before-closing-bracket");
|
|
1964
|
+
else if (spaces !== " ") report(spacesStart, spacesEnd, "space-width");
|
|
1965
|
+
}
|
|
1966
|
+
}
|
|
1650
1967
|
});
|
|
1651
1968
|
//#endregion
|
|
1652
1969
|
//#region src/proofreading/rules/variant-character.ts
|
|
@@ -1672,21 +1989,27 @@ const variantCharacterRule = () => defineParsedRule("kg/variant-character", "異
|
|
|
1672
1989
|
/**
|
|
1673
1990
|
* The built-in rule set at its default configuration. Infallible by construction: every rule is
|
|
1674
1991
|
* built from constants, so there is no options error for a caller to handle.
|
|
1992
|
+
*
|
|
1993
|
+
* Rules whose answer depends on the work's own conventions — which width numerals take, whether a
|
|
1994
|
+
* word is written in kanji or kana — are exported individually instead of included here.
|
|
1675
1995
|
*/
|
|
1676
1996
|
function createDefaultProofreadingRules() {
|
|
1677
1997
|
return [
|
|
1678
|
-
|
|
1998
|
+
paragraphOpeningRule(),
|
|
1679
1999
|
punctuationBeforeClosingQuoteRule(),
|
|
1680
2000
|
spaceAfterQuestionOrExclamationRule(),
|
|
1681
2001
|
evenEllipsisRule(),
|
|
1682
2002
|
evenDashRule(),
|
|
2003
|
+
ellipsisCharacterRule(),
|
|
2004
|
+
dashCharacterRule(),
|
|
1683
2005
|
noConsecutivePunctuationRule(),
|
|
1684
2006
|
noConsecutiveInterpunctRule(),
|
|
1685
2007
|
noConsecutiveChoonpuRule(),
|
|
1686
2008
|
minusBeforeNumberRule(),
|
|
1687
2009
|
maxArabicNumeralDigitsRule(),
|
|
2010
|
+
fullwidthJapanesePunctuationRule(),
|
|
1688
2011
|
variantCharacterRule()
|
|
1689
2012
|
];
|
|
1690
2013
|
}
|
|
1691
2014
|
//#endregion
|
|
1692
|
-
export { BoldAnnotation, ComposeError, CompositionStatistics, DiagnosticOrigin, DiagnosticSeverity, DisplayRange, EmphasisAnnotation, FontPreset, FontPresetId, FontSizePt, GraphemeRange, GridCell, GridLine, GridPage, GridSettings, GridStage, InvalidRuleOptions, ItalicAnnotation, LineOffset, ManuscriptAnnotation, ManuscriptAppearanceSettings, ManuscriptCompositionSettings, ManuscriptDiagnostic, ManuscriptGeometry, ManuscriptGridLayout, ManuscriptOffsets, ManuscriptRange, ManuscriptResult, NamespacedId, PaperSize, PaperSizeId, ParseError, ParsedGrapheme, ParsedManuscript, ProofreadError, ProofreadingReport, ProofreadingRuleMeta, Rejection, RubyAnnotation, SourcePosition, SourceRange, TextRange, ValidationIssue, assertNever, composeManuscript, createDefaultProofreadingRules, createMaxArabicNumeralDigitsRule,
|
|
2015
|
+
export { BoldAnnotation, ComposeError, CompositionStatistics, DiagnosticOrigin, DiagnosticSeverity, DisplayRange, EmphasisAnnotation, FontPreset, FontPresetId, FontSizePt, GraphemeRange, GridCell, GridLine, GridPage, GridSettings, GridStage, InvalidRuleOptions, ItalicAnnotation, LineOffset, ManuscriptAnnotation, ManuscriptAppearanceSettings, ManuscriptCompositionSettings, ManuscriptDiagnostic, ManuscriptGeometry, ManuscriptGridLayout, ManuscriptOffsets, ManuscriptRange, ManuscriptResult, NamespacedId, PaperSize, PaperSizeId, ParseError, ParsedGrapheme, ParsedManuscript, ProofreadError, ProofreadingReport, ProofreadingRuleMeta, Rejection, RubyAnnotation, SourcePosition, SourceRange, TextRange, ValidationIssue, assertNever, composeManuscript, consistentKanjiOpeningRule, consistentLatinWidthRule, consistentNumeralWidthRule, createConsistentKanjiOpeningRule, createDefaultProofreadingRules, createMaxArabicNumeralDigitsRule, createParagraphOpeningRule, dashCharacterRule, ellipsisCharacterRule, evenDashRule, evenEllipsisRule, fullwidthJapanesePunctuationRule, kakuyomuParser, manuscriptGridComposer, maxArabicNumeralDigitsRule, minusBeforeNumberRule, mmToPt, noConsecutiveChoonpuRule, noConsecutiveInterpunctRule, noConsecutivePunctuationRule, paragraphOpeningRule, parseManuscript, pixivParser, plainTextParser, proofreadManuscript, ptToMm, punctuationBeforeClosingQuoteRule, spaceAfterQuestionOrExclamationRule, variantCharacterRule };
|