@sushichan044/kg-core 0.11.1 → 0.11.3

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/dist/index.mjs CHANGED
@@ -1,5 +1,5 @@
1
- import { c as assertNever, d as ManuscriptResult, f as ManuscriptDiagnostic, h as ManuscriptRange, l as graphemeSegmenter, m as NamespacedId, u as ValidationIssue, y as readonlyObject } from "./question-or-exclamation-spacing-C5cFLeKr.mjs";
2
- import { _ as ParsedManuscript, c as NovelFlowSettings, d as ManuscriptPageSettings, f as PaperSize, g as FontPresetId, h as FontSizeQ, l as ManuscriptOffsets, m as PaperSizeId, n as novelComposer, p as ManuscriptAppearanceSettings, s as NovelCompositionSettings, u as ManuscriptGeometry } from "./novel-composer-z0cv8OHb.mjs";
1
+ import { _ as ManuscriptRange, d as graphemeSegmenter, f as ValidationIssue, g as NamespacedId, m as ManuscriptDiagnostic, p as ManuscriptResult, u as assertNever, x as readonlyObject } from "./question-or-exclamation-spacing-D7TSDUG8.mjs";
2
+ import { _ as ParsedManuscript, c as NovelFlowSettings, d as ManuscriptPageSettings, f as PaperSize, g as FontPresetId, h as FontSizeQ, l as ManuscriptOffsets, m as PaperSizeId, n as novelComposer, p as ManuscriptAppearanceSettings, s as NovelCompositionSettings, u as ManuscriptGeometry } from "./novel-composer-DNsKrJIP.mjs";
3
3
  import { t as describeCause } from "./describe-cause-SABI_1ex.mjs";
4
4
  import * as v from "valibot";
5
5
  const Rejection = { schema: readonlyObject({ reason: v.string() }) };
@@ -598,16 +598,48 @@ function joinIssues(issues) {
598
598
  }
599
599
  //#endregion
600
600
  //#region src/appearance/font-preset.ts
601
+ const FIXED_PITCH = {
602
+ features: {
603
+ palt: 0,
604
+ vpal: 0,
605
+ halt: 0,
606
+ vhal: 0,
607
+ vkrn: 0,
608
+ liga: 1
609
+ },
610
+ westernKerning: "normal",
611
+ synthesis: "weight style"
612
+ };
601
613
  const FONT_PRESETS = {
602
614
  mincho: {
603
615
  id: "mincho",
604
- label: "明朝",
605
- family: "\"Yu Mincho\", \"Hiragino Mincho ProN\", \"Hiragino Mincho Pro\", serif"
616
+ label: "倫明朝",
617
+ fontName: "KGRinMincho100",
618
+ family: "\"KGRinMincho100\", \"Yu Mincho\", \"Hiragino Mincho ProN\", serif",
619
+ textTransforms: ["combine-kana-voicing-marks"],
620
+ measurement: "browser-shaped",
621
+ rendering: {
622
+ ...FIXED_PITCH,
623
+ synthesis: "style"
624
+ }
606
625
  },
607
626
  gothic: {
608
627
  id: "gothic",
609
628
  label: "ゴシック",
610
- family: "\"Yu Gothic\", \"Hiragino Kaku Gothic ProN\", system-ui, sans-serif"
629
+ fontName: "",
630
+ family: "\"Yu Gothic\", \"Hiragino Kaku Gothic ProN\", system-ui, sans-serif",
631
+ textTransforms: [],
632
+ measurement: "logical",
633
+ rendering: FIXED_PITCH
634
+ },
635
+ "genei-koburi": {
636
+ id: "genei-koburi",
637
+ label: "源暎こぶり明朝",
638
+ fontName: "KGGenEiKoburi61",
639
+ family: "\"KGGenEiKoburi61\", \"Yu Mincho\", \"Hiragino Mincho ProN\", serif",
640
+ textTransforms: [],
641
+ measurement: "browser-shaped",
642
+ rendering: FIXED_PITCH
611
643
  }
612
644
  };
613
645
  const FontPreset = {
@@ -615,4 +647,123 @@ const FontPreset = {
615
647
  all: Object.values(FONT_PRESETS)
616
648
  };
617
649
  //#endregion
618
- export { ComposeError, FontPreset, FontPresetId, FontSizeQ, ManuscriptAppearanceSettings, ManuscriptDiagnostic, ManuscriptGeometry, ManuscriptOffsets, ManuscriptPageSettings, ManuscriptRange, ManuscriptResult, NovelCompositionSettings, NovelFlowSettings, PaperSize, PaperSizeId, ParseError, composeManuscript, kakuyomuParser, novelComposer, parseManuscript, pixivParser, plainTextParser };
650
+ //#region src/appearance/internal/font-text-transforms.ts
651
+ const transforms = { "combine-kana-voicing-marks": (text) => text.replace(/([\u3041-\u3096\u30A1-\u30FA\u31F0-\u31FF])([\u309B\u309C])/gu, (_, kana, mark) => kana + (mark === "゛" ? "゙" : "゚")) };
652
+ function applyFontTextTransforms(text, rules) {
653
+ return rules.reduce((value, rule) => transforms[rule](value), text);
654
+ }
655
+ //#endregion
656
+ //#region src/appearance/font-preparation.ts
657
+ function prepareTextForFont(text, fontPreset) {
658
+ return applyFontTextTransforms(text, FontPreset.of(fontPreset).textTransforms);
659
+ }
660
+ /**
661
+ * Prepare display text after parsing; source and UTF-16 offsets remain unchanged.
662
+ */
663
+ function prepareManuscriptForFont(parsed, fontPreset) {
664
+ if (FontPreset.of(fontPreset).textTransforms.length === 0) return {
665
+ parsed,
666
+ mapRange: (range) => range
667
+ };
668
+ const boundaries = /* @__PURE__ */ new Set([0, parsed.displayText.length]);
669
+ for (const annotation of parsed.annotations) {
670
+ boundaries.add(annotation.range.display.start);
671
+ boundaries.add(annotation.range.display.end);
672
+ if (annotation.kind === "ruby" && annotation.reading.kind !== "group") for (const member of parsed.graphemes.slice(annotation.range.graphemes.start, annotation.range.graphemes.end)) boundaries.add(member.range.display.start);
673
+ }
674
+ for (const [index, member] of parsed.graphemes.entries()) {
675
+ const previous = parsed.graphemes[index - 1];
676
+ if (previous !== void 0 && previous.range.source.end !== member.range.source.start) boundaries.add(member.range.display.start);
677
+ }
678
+ const ordered = [...boundaries].sort((a, b) => a - b);
679
+ const parts = [];
680
+ const graphemes = [];
681
+ let originalIndex = 0;
682
+ for (let i = 1; i < ordered.length; i += 1) {
683
+ const start = ordered[i - 1];
684
+ const end = ordered[i];
685
+ if (start === void 0 || end === void 0) continue;
686
+ const text = prepareTextForFont(parsed.displayText.slice(start, end), fontPreset);
687
+ parts.push(text);
688
+ for (const { segment, index } of graphemeSegmenter.segment(text)) {
689
+ const displayStart = start + index;
690
+ const displayEnd = displayStart + segment.length;
691
+ while ((parsed.graphemes[originalIndex]?.range.display.end ?? Infinity) <= displayStart) originalIndex += 1;
692
+ const first = parsed.graphemes[originalIndex];
693
+ let last = first;
694
+ while (last !== void 0 && last.range.display.end < displayEnd) {
695
+ originalIndex += 1;
696
+ last = parsed.graphemes[originalIndex];
697
+ }
698
+ if (first === void 0 || last === void 0) throw new Error("Font preparation lost a source member");
699
+ graphemes.push({
700
+ value: segment,
701
+ range: ManuscriptRange.of({
702
+ source: {
703
+ start: first.range.source.start,
704
+ end: last.range.source.end
705
+ },
706
+ display: {
707
+ start: displayStart,
708
+ end: displayEnd
709
+ },
710
+ graphemes: {
711
+ start: graphemes.length,
712
+ end: graphemes.length + 1
713
+ }
714
+ })
715
+ });
716
+ }
717
+ }
718
+ const boundaryIndex = (offset, end) => {
719
+ let low = 0;
720
+ let high = graphemes.length;
721
+ while (low < high) {
722
+ const mid = Math.floor((low + high) / 2);
723
+ const member = graphemes[mid];
724
+ if (member !== void 0 && (end ? member.range.display.start < offset : member.range.display.end <= offset)) low = mid + 1;
725
+ else high = mid;
726
+ }
727
+ return low;
728
+ };
729
+ const mapRange = (range) => {
730
+ const start = boundaryIndex(range.display.start, false);
731
+ return ManuscriptRange.of({
732
+ ...range,
733
+ graphemes: {
734
+ start,
735
+ end: range.display.start === range.display.end ? start : boundaryIndex(range.display.end, true)
736
+ }
737
+ });
738
+ };
739
+ const annotations = parsed.annotations.map((annotation) => {
740
+ const range = mapRange(annotation.range);
741
+ if (annotation.kind !== "ruby") return {
742
+ ...annotation,
743
+ range
744
+ };
745
+ const reading = annotation.reading.kind === "group" ? {
746
+ kind: "group",
747
+ text: prepareTextForFont(annotation.reading.text, fontPreset)
748
+ } : {
749
+ ...annotation.reading,
750
+ segments: annotation.reading.segments.map((text) => prepareTextForFont(text, fontPreset))
751
+ };
752
+ return {
753
+ ...annotation,
754
+ range,
755
+ reading
756
+ };
757
+ });
758
+ return {
759
+ parsed: v.parse(ParsedManuscript.contractFor(parsed.source), {
760
+ source: parsed.source,
761
+ displayText: parts.join(""),
762
+ graphemes,
763
+ annotations
764
+ }),
765
+ mapRange
766
+ };
767
+ }
768
+ //#endregion
769
+ export { ComposeError, FontPreset, FontPresetId, FontSizeQ, ManuscriptAppearanceSettings, ManuscriptDiagnostic, ManuscriptGeometry, ManuscriptOffsets, ManuscriptPageSettings, ManuscriptRange, ManuscriptResult, NovelCompositionSettings, NovelFlowSettings, PaperSize, PaperSizeId, ParseError, composeManuscript, kakuyomuParser, novelComposer, parseManuscript, pixivParser, plainTextParser, prepareManuscriptForFont, prepareTextForFont };
package/dist/lint.d.mts CHANGED
@@ -440,13 +440,11 @@ export declare function createParagraphOpeningRule(options?: ParagraphOpeningOpt
440
440
  export declare const punctuationBeforeClosingQuoteRule: () => ParsedProofreadingRule;
441
441
  //#endregion
442
442
  //#region src/proofreading/rules/space-after-question-or-exclamation.d.ts
443
- /**
444
- * The gap that follows every run of ! or ? (区切り約物, JLReq 3.1.6). A dividing punctuation mark ends a
445
- * sentence without a full stop, so a full em of white stands in for the one a 句点 would have
446
- * carried. A run at the end of a line or right before a closing bracket is already separated from
447
- * what follows and needs no gap; anywhere else it takes exactly one ideographic space.
448
- */
449
443
  export declare const spaceAfterQuestionOrExclamationRule: () => ParsedProofreadingRule;
444
+ type SpaceAfterQuestionOrExclamationOptions = Readonly<{
445
+ additionalSentenceEndingMarks?: string;
446
+ }>;
447
+ export declare function createSpaceAfterQuestionOrExclamationRule(options?: SpaceAfterQuestionOrExclamationOptions): ManuscriptResult<ParsedProofreadingRule, InvalidRuleOptions>;
450
448
  //#endregion
451
449
  //#region src/proofreading/rules/variant-character.d.ts
452
450
  /**
@@ -458,4 +456,4 @@ export declare const spaceAfterQuestionOrExclamationRule: () => ParsedProofreadi
458
456
  */
459
457
  export declare const variantCharacterRule: () => ParsedProofreadingRule;
460
458
  //#endregion
461
- export type { ComposedProofreadingRule, ConsistentKanjiOpeningOptions, DashOptions, KanjiOpeningPair, MaxArabicNumeralDigitsOptions, ParagraphOpeningOptions, ParsedProofreadingRule, ProofreadOptions, ProofreadingReport, ProofreadingRule, ProofreadingRuleContext, ProofreadingRuleMessages };
459
+ export type { ComposedProofreadingRule, ConsistentKanjiOpeningOptions, DashOptions, KanjiOpeningPair, MaxArabicNumeralDigitsOptions, ParagraphOpeningOptions, ParsedProofreadingRule, ProofreadOptions, ProofreadingReport, ProofreadingRule, ProofreadingRuleContext, ProofreadingRuleMessages, SpaceAfterQuestionOrExclamationOptions };
package/dist/lint.mjs CHANGED
@@ -1,4 +1,4 @@
1
- import { a as CLOSING_BRACKETS, c as assertNever, d as ManuscriptResult, f as ManuscriptDiagnostic, h as ManuscriptRange, l as graphemeSegmenter, m as NamespacedId, n as leadingSpaces, o as OPENING_BRACKETS, p as DiagnosticSeverity, s as characterClass, t as questionOrExclamationSpacings, u as ValidationIssue, v as readonlyArray, y as readonlyObject } from "./question-or-exclamation-spacing-C5cFLeKr.mjs";
1
+ import { _ as ManuscriptRange, a as characterClass, b as readonlyArray, d as graphemeSegmenter, f as ValidationIssue, g as NamespacedId, h as DiagnosticSeverity, i as OPENING_BRACKETS, l as validAdditionalSentenceEndingMarks, m as ManuscriptDiagnostic, n as leadingSpaces, p as ManuscriptResult, r as CLOSING_BRACKETS, t as questionOrExclamationSpacings, u as assertNever, x as readonlyObject } from "./question-or-exclamation-spacing-D7TSDUG8.mjs";
2
2
  import { t as describeCause } from "./describe-cause-SABI_1ex.mjs";
3
3
  import * as v from "valibot";
4
4
  //#region src/proofreading/invalid-rule-options.ts
@@ -333,7 +333,7 @@ const DEFAULT_PAIRS = [
333
333
  * Reports the first kanji occurrence of every pair the manuscript also writes in kana. Whether the
334
334
  * two spellings are a deliberate distinction is the author's call, so the finding is a warning.
335
335
  */
336
- function build$3(pairs) {
336
+ function build$4(pairs) {
337
337
  return defineParsedRule(RULE_ID$5, MESSAGE, (manuscript, report) => {
338
338
  for (const { closed, opened } of pairs) {
339
339
  if (!manuscript.displayText.includes(opened)) continue;
@@ -349,7 +349,7 @@ function build$3(pairs) {
349
349
  }
350
350
  });
351
351
  }
352
- const consistentKanjiOpeningRule = () => build$3(DEFAULT_PAIRS);
352
+ const consistentKanjiOpeningRule = () => build$4(DEFAULT_PAIRS);
353
353
  function createConsistentKanjiOpeningRule(options = {}) {
354
354
  if (options.pairs === void 0) return ManuscriptResult.succeed(consistentKanjiOpeningRule());
355
355
  const pairs = v.safeParse(PairsSchema, options.pairs);
@@ -359,7 +359,7 @@ function createConsistentKanjiOpeningRule(options = {}) {
359
359
  option: "pairs",
360
360
  issues: ValidationIssue.from(pairs.issues)
361
361
  });
362
- return ManuscriptResult.succeed(build$3(pairs.output));
362
+ return ManuscriptResult.succeed(build$4(pairs.output));
363
363
  }
364
364
  //#endregion
365
365
  //#region src/proofreading/rules/internal/mixed-width.ts
@@ -431,7 +431,7 @@ function messageIdFor(run, preferred) {
431
431
  * must match, since only a repeat of the same character joins without a seam. JLReq classes the
432
432
  * dash as 分離禁止文字 (cl-08) for the same reason: the pair must not be split across lines.
433
433
  */
434
- function build$2(preferred) {
434
+ function build$3(preferred) {
435
435
  const messages = {
436
436
  character: `ダッシュには「${preferred}」を使ってください`,
437
437
  "even-count": EVEN_COUNT_MESSAGE
@@ -462,7 +462,7 @@ function build$2(preferred) {
462
462
  }
463
463
  };
464
464
  }
465
- const dashRule = () => build$2(DEFAULT_PREFERRED);
465
+ const dashRule = () => build$3(DEFAULT_PREFERRED);
466
466
  function createDashRule(options = {}) {
467
467
  if (options.preferred === void 0) return ManuscriptResult.succeed(dashRule());
468
468
  const preferred = v.safeParse(DashCharacterSchema, options.preferred);
@@ -472,7 +472,7 @@ function createDashRule(options = {}) {
472
472
  option: "preferred",
473
473
  issues: ValidationIssue.from(preferred.issues)
474
474
  });
475
- return ManuscriptResult.succeed(build$2(preferred.output));
475
+ return ManuscriptResult.succeed(build$3(preferred.output));
476
476
  }
477
477
  //#endregion
478
478
  //#region src/proofreading/rules/ellipsis-character.ts
@@ -582,7 +582,7 @@ const MaxDigitsSchema = v.pipe(v.number(), v.finite(), v.integer(), v.minValue(1
582
582
  * upright inside one em, but a longer one has nowhere to go: it either turns the line sideways or
583
583
  * breaks across it. The usual limit is two digits, past which a novel spells the number in kanji.
584
584
  */
585
- function build$1(maxDigits) {
585
+ function build$2(maxDigits) {
586
586
  return defineMatchRule({
587
587
  id: RULE_ID$2,
588
588
  pattern: /([0-90-9]+)(?:[..]([0-90-9]+))?/gu,
@@ -590,7 +590,7 @@ function build$1(maxDigits) {
590
590
  message: `${maxDigits}桁を超えるアラビア数字が使われています`
591
591
  });
592
592
  }
593
- const maxArabicNumeralDigitsRule = () => build$1(DEFAULT_MAX_DIGITS);
593
+ const maxArabicNumeralDigitsRule = () => build$2(DEFAULT_MAX_DIGITS);
594
594
  function createMaxArabicNumeralDigitsRule(options = {}) {
595
595
  if (options.maxDigits === void 0) return ManuscriptResult.succeed(maxArabicNumeralDigitsRule());
596
596
  const maxDigits = v.safeParse(MaxDigitsSchema, options.maxDigits);
@@ -600,7 +600,7 @@ function createMaxArabicNumeralDigitsRule(options = {}) {
600
600
  option: "maxDigits",
601
601
  issues: ValidationIssue.from(maxDigits.issues)
602
602
  });
603
- return ManuscriptResult.succeed(build$1(maxDigits.output));
603
+ return ManuscriptResult.succeed(build$2(maxDigits.output));
604
604
  }
605
605
  //#endregion
606
606
  //#region src/proofreading/rules/minus-before-number.ts
@@ -664,7 +664,7 @@ const OpeningBracketsSchema = v.pipe(v.string(), v.nonEmpty());
664
664
  * The three findings are branches of that one decision rather than separate rules, so a line can
665
665
  * never collect two of them at once.
666
666
  */
667
- function build(openingBrackets) {
667
+ function build$1(openingBrackets) {
668
668
  return {
669
669
  kind: "parsed",
670
670
  meta: {
@@ -693,7 +693,7 @@ function build(openingBrackets) {
693
693
  }
694
694
  };
695
695
  }
696
- const paragraphOpeningRule = () => build(OPENING_BRACKETS);
696
+ const paragraphOpeningRule = () => build$1(OPENING_BRACKETS);
697
697
  function createParagraphOpeningRule(options = {}) {
698
698
  if (options.openingBrackets === void 0) return ManuscriptResult.succeed(paragraphOpeningRule());
699
699
  const brackets = v.safeParse(OpeningBracketsSchema, options.openingBrackets);
@@ -703,7 +703,7 @@ function createParagraphOpeningRule(options = {}) {
703
703
  option: "openingBrackets",
704
704
  issues: ValidationIssue.from(brackets.issues)
705
705
  });
706
- return ManuscriptResult.succeed(build(brackets.output));
706
+ return ManuscriptResult.succeed(build$1(brackets.output));
707
707
  }
708
708
  //#endregion
709
709
  //#region src/proofreading/rules/punctuation-before-closing-quote.ts
@@ -722,8 +722,8 @@ const punctuationBeforeClosingQuoteRule = () => defineMatchRule({
722
722
  //#region src/proofreading/rules/space-after-question-or-exclamation.ts
723
723
  const RULE_ID = "kg/space-after-question-or-exclamation";
724
724
  const MESSAGES = {
725
- default: "感嘆符または疑問符の直後には全角スペースか閉じ括弧が必要です",
726
- "space-width": "感嘆符または疑問符の直後の空白は全角スペース1字にしてください",
725
+ default: "文末記号の直後には全角スペースか閉じ括弧が必要です",
726
+ "space-width": "文末記号の直後の空白は全角スペース1字にしてください",
727
727
  "before-closing-bracket": "閉じ括弧の直前に空白を置くことはできません"
728
728
  };
729
729
  /**
@@ -732,7 +732,7 @@ const MESSAGES = {
732
732
  * carried. A run at the end of a line or right before a closing bracket is already separated from
733
733
  * what follows and needs no gap; anywhere else it takes exactly one ideographic space.
734
734
  */
735
- const spaceAfterQuestionOrExclamationRule = () => ({
735
+ const build = (additionalSentenceEndingMarks = "") => ({
736
736
  kind: "parsed",
737
737
  meta: {
738
738
  id: RULE_ID,
@@ -745,7 +745,7 @@ const spaceAfterQuestionOrExclamationRule = () => ({
745
745
  messageId
746
746
  });
747
747
  };
748
- for (const line of splitDisplayLines(manuscript.displayText)) for (const spacing of questionOrExclamationSpacings(line.text)) switch (spacing.kind) {
748
+ for (const line of splitDisplayLines(manuscript.displayText)) for (const spacing of questionOrExclamationSpacings(line.text, additionalSentenceEndingMarks)) switch (spacing.kind) {
749
749
  case "valid": break;
750
750
  case "missing":
751
751
  report(line.start + spacing.marks.start, line.start + spacing.marks.end, "default");
@@ -760,6 +760,17 @@ const spaceAfterQuestionOrExclamationRule = () => ({
760
760
  }
761
761
  }
762
762
  });
763
+ const spaceAfterQuestionOrExclamationRule = () => build();
764
+ function createSpaceAfterQuestionOrExclamationRule(options = {}) {
765
+ const result = v.safeParse(v.pipe(v.string(), v.check(validAdditionalSentenceEndingMarks)), options.additionalSentenceEndingMarks === void 0 ? "" : options.additionalSentenceEndingMarks);
766
+ if (!result.success) return ManuscriptResult.fail({
767
+ kind: "InvalidRuleOptions",
768
+ ruleId: RULE_ID,
769
+ option: "additionalSentenceEndingMarks",
770
+ issues: ValidationIssue.from(result.issues)
771
+ });
772
+ return ManuscriptResult.succeed(build(result.output));
773
+ }
763
774
  //#endregion
764
775
  //#region src/proofreading/rules/variant-character.ts
765
776
  /**
@@ -809,4 +820,4 @@ function createDefaultProofreadingRules() {
809
820
  ];
810
821
  }
811
822
  //#endregion
812
- export { InvalidRuleOptions, ProofreadError, ProofreadingRuleMeta, consistentKanjiOpeningRule, consistentLatinWidthRule, consistentNumeralWidthRule, createConsistentKanjiOpeningRule, createDashRule, createDefaultProofreadingRules, createMaxArabicNumeralDigitsRule, createParagraphOpeningRule, dashRule, ellipsisCharacterRule, evenEllipsisRule, fullwidthJapanesePunctuationRule, maxArabicNumeralDigitsRule, minusBeforeNumberRule, noConsecutiveInterpunctRule, noConsecutivePunctuationRule, paragraphOpeningRule, proofreadManuscript, punctuationBeforeClosingQuoteRule, spaceAfterQuestionOrExclamationRule, variantCharacterRule };
823
+ export { InvalidRuleOptions, ProofreadError, ProofreadingRuleMeta, consistentKanjiOpeningRule, consistentLatinWidthRule, consistentNumeralWidthRule, createConsistentKanjiOpeningRule, createDashRule, createDefaultProofreadingRules, createMaxArabicNumeralDigitsRule, createParagraphOpeningRule, createSpaceAfterQuestionOrExclamationRule, dashRule, ellipsisCharacterRule, evenEllipsisRule, fullwidthJapanesePunctuationRule, maxArabicNumeralDigitsRule, minusBeforeNumberRule, noConsecutiveInterpunctRule, noConsecutivePunctuationRule, paragraphOpeningRule, proofreadManuscript, punctuationBeforeClosingQuoteRule, spaceAfterQuestionOrExclamationRule, variantCharacterRule };