@sushichan044/kg-core 0.6.0 → 0.6.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/dist/index.d.mts +244 -244
- package/dist/index.mjs +81 -29
- package/package.json +1 -1
package/dist/index.mjs
CHANGED
|
@@ -1544,7 +1544,7 @@ function defineMatchRule(options) {
|
|
|
1544
1544
|
}
|
|
1545
1545
|
//#endregion
|
|
1546
1546
|
//#region src/proofreading/rules/consistent-kanji-opening.ts
|
|
1547
|
-
const RULE_ID$
|
|
1547
|
+
const RULE_ID$6 = "kg/consistent-kanji-opening";
|
|
1548
1548
|
const MESSAGE = "「{{ closed }}」と「{{ opened }}」が混在しています。文脈上の使い分けか表記ゆれかを確認してください";
|
|
1549
1549
|
const KanjiOpeningPairSchema = v.pipe(readonlyObject({
|
|
1550
1550
|
closed: v.pipe(v.string(), v.nonEmpty()),
|
|
@@ -1598,7 +1598,7 @@ const DEFAULT_PAIRS = [
|
|
|
1598
1598
|
* two spellings are a deliberate distinction is the author's call, so the finding is a warning.
|
|
1599
1599
|
*/
|
|
1600
1600
|
function build$3(pairs) {
|
|
1601
|
-
return defineParsedRule(RULE_ID$
|
|
1601
|
+
return defineParsedRule(RULE_ID$6, MESSAGE, (manuscript, report) => {
|
|
1602
1602
|
for (const { closed, opened } of pairs) {
|
|
1603
1603
|
if (!manuscript.displayText.includes(opened)) continue;
|
|
1604
1604
|
const index = manuscript.displayText.indexOf(closed);
|
|
@@ -1619,7 +1619,7 @@ function createConsistentKanjiOpeningRule(options = {}) {
|
|
|
1619
1619
|
const pairs = v.safeParse(PairsSchema, options.pairs);
|
|
1620
1620
|
if (!pairs.success) return ManuscriptResult.fail({
|
|
1621
1621
|
kind: "InvalidRuleOptions",
|
|
1622
|
-
ruleId: RULE_ID$
|
|
1622
|
+
ruleId: RULE_ID$6,
|
|
1623
1623
|
option: "pairs",
|
|
1624
1624
|
issues: ValidationIssue.from(pairs.issues)
|
|
1625
1625
|
});
|
|
@@ -1664,7 +1664,7 @@ const consistentNumeralWidthRule = () => defineMixedWidthRule({
|
|
|
1664
1664
|
});
|
|
1665
1665
|
//#endregion
|
|
1666
1666
|
//#region src/proofreading/rules/dash.ts
|
|
1667
|
-
const RULE_ID$
|
|
1667
|
+
const RULE_ID$5 = "kg/dash";
|
|
1668
1668
|
const DEFAULT_PREFERRED = "―";
|
|
1669
1669
|
const DashCharacterSchema = v.picklist([
|
|
1670
1670
|
"―",
|
|
@@ -1686,7 +1686,7 @@ function build$2(preferred) {
|
|
|
1686
1686
|
return {
|
|
1687
1687
|
kind: "parsed",
|
|
1688
1688
|
meta: {
|
|
1689
|
-
id: RULE_ID$
|
|
1689
|
+
id: RULE_ID$5,
|
|
1690
1690
|
messages
|
|
1691
1691
|
},
|
|
1692
1692
|
check: (manuscript, context) => {
|
|
@@ -1715,7 +1715,7 @@ function createDashRule(options = {}) {
|
|
|
1715
1715
|
const preferred = v.safeParse(DashCharacterSchema, options.preferred);
|
|
1716
1716
|
if (!preferred.success) return ManuscriptResult.fail({
|
|
1717
1717
|
kind: "InvalidRuleOptions",
|
|
1718
|
-
ruleId: RULE_ID$
|
|
1718
|
+
ruleId: RULE_ID$5,
|
|
1719
1719
|
option: "preferred",
|
|
1720
1720
|
issues: ValidationIssue.from(preferred.issues)
|
|
1721
1721
|
});
|
|
@@ -1742,8 +1742,8 @@ const evenEllipsisRule = () => defineMatchRule({
|
|
|
1742
1742
|
});
|
|
1743
1743
|
//#endregion
|
|
1744
1744
|
//#region src/proofreading/rules/fullwidth-japanese-punctuation.ts
|
|
1745
|
-
const RULE_ID$
|
|
1746
|
-
const MESSAGES$
|
|
1745
|
+
const RULE_ID$4 = "kg/fullwidth-japanese-punctuation";
|
|
1746
|
+
const MESSAGES$3 = {
|
|
1747
1747
|
"halfwidth-japanese-punctuation": "半角の「{{ character }}」があります。日本語の句読点・括弧・感嘆符・疑問符は全角にしてください",
|
|
1748
1748
|
"halfwidth-near-japanese": "日本語の前後に半角の「{{ character }}」があります。全角にすべきか確認してください"
|
|
1749
1749
|
};
|
|
@@ -1788,8 +1788,8 @@ function isEllipsisSubstitute(text, index) {
|
|
|
1788
1788
|
const fullwidthJapanesePunctuationRule = () => ({
|
|
1789
1789
|
kind: "parsed",
|
|
1790
1790
|
meta: {
|
|
1791
|
-
id: RULE_ID$
|
|
1792
|
-
messages: MESSAGES$
|
|
1791
|
+
id: RULE_ID$4,
|
|
1792
|
+
messages: MESSAGES$3
|
|
1793
1793
|
},
|
|
1794
1794
|
check: (manuscript, context) => {
|
|
1795
1795
|
for (const line of splitDisplayLines(manuscript.displayText)) for (const { pattern, messageId, severity, requiresJapanese } of CHECKS) for (const match of line.text.matchAll(pattern)) {
|
|
@@ -1807,12 +1807,12 @@ const fullwidthJapanesePunctuationRule = () => ({
|
|
|
1807
1807
|
});
|
|
1808
1808
|
//#endregion
|
|
1809
1809
|
//#region src/proofreading/rules/max-arabic-numeral-digits.ts
|
|
1810
|
-
const RULE_ID$
|
|
1810
|
+
const RULE_ID$3 = "kg/max-arabic-numeral-digits";
|
|
1811
1811
|
const DEFAULT_MAX_DIGITS = 2;
|
|
1812
1812
|
const MaxDigitsSchema = v.pipe(v.number(), v.finite(), v.integer(), v.minValue(1));
|
|
1813
1813
|
function build$1(maxDigits) {
|
|
1814
1814
|
return defineMatchRule({
|
|
1815
|
-
id: RULE_ID$
|
|
1815
|
+
id: RULE_ID$3,
|
|
1816
1816
|
pattern: /([0-90-9]+)(?:[..]([0-90-9]+))?/gu,
|
|
1817
1817
|
accept: (match) => (match[1]?.length ?? 0) > maxDigits || (match[2]?.length ?? 0) > maxDigits,
|
|
1818
1818
|
message: `${maxDigits}桁を超えるアラビア数字が使われています`
|
|
@@ -1824,7 +1824,7 @@ function createMaxArabicNumeralDigitsRule(options = {}) {
|
|
|
1824
1824
|
const maxDigits = v.safeParse(MaxDigitsSchema, options.maxDigits);
|
|
1825
1825
|
if (!maxDigits.success) return ManuscriptResult.fail({
|
|
1826
1826
|
kind: "InvalidRuleOptions",
|
|
1827
|
-
ruleId: RULE_ID$
|
|
1827
|
+
ruleId: RULE_ID$3,
|
|
1828
1828
|
option: "maxDigits",
|
|
1829
1829
|
issues: ValidationIssue.from(maxDigits.issues)
|
|
1830
1830
|
});
|
|
@@ -1891,8 +1891,8 @@ function leadingSpaces(text) {
|
|
|
1891
1891
|
}
|
|
1892
1892
|
//#endregion
|
|
1893
1893
|
//#region src/proofreading/rules/paragraph-opening.ts
|
|
1894
|
-
const RULE_ID$
|
|
1895
|
-
const MESSAGES$
|
|
1894
|
+
const RULE_ID$2 = "kg/paragraph-opening";
|
|
1895
|
+
const MESSAGES$2 = {
|
|
1896
1896
|
"leading-character": "段落の先頭には全角スペースまたは開き括弧が必要です",
|
|
1897
1897
|
"indent-width": "段落冒頭の字下げは全角スペース1字にしてください",
|
|
1898
1898
|
"unexpected-indent": "括弧から始まる段落を字下げすることはできません"
|
|
@@ -1907,8 +1907,8 @@ function build(openingBrackets) {
|
|
|
1907
1907
|
return {
|
|
1908
1908
|
kind: "parsed",
|
|
1909
1909
|
meta: {
|
|
1910
|
-
id: RULE_ID$
|
|
1911
|
-
messages: MESSAGES$
|
|
1910
|
+
id: RULE_ID$2,
|
|
1911
|
+
messages: MESSAGES$2
|
|
1912
1912
|
},
|
|
1913
1913
|
check: (manuscript, context) => {
|
|
1914
1914
|
const report = (start, end, messageId) => {
|
|
@@ -1938,7 +1938,7 @@ function createParagraphOpeningRule(options = {}) {
|
|
|
1938
1938
|
const brackets = v.safeParse(OpeningBracketsSchema, options.openingBrackets);
|
|
1939
1939
|
if (!brackets.success) return ManuscriptResult.fail({
|
|
1940
1940
|
kind: "InvalidRuleOptions",
|
|
1941
|
-
ruleId: RULE_ID$
|
|
1941
|
+
ruleId: RULE_ID$2,
|
|
1942
1942
|
option: "openingBrackets",
|
|
1943
1943
|
issues: ValidationIssue.from(brackets.issues)
|
|
1944
1944
|
});
|
|
@@ -1954,8 +1954,8 @@ const punctuationBeforeClosingQuoteRule = () => defineMatchRule({
|
|
|
1954
1954
|
});
|
|
1955
1955
|
//#endregion
|
|
1956
1956
|
//#region src/proofreading/rules/space-after-question-or-exclamation.ts
|
|
1957
|
-
const RULE_ID = "kg/space-after-question-or-exclamation";
|
|
1958
|
-
const MESSAGES = {
|
|
1957
|
+
const RULE_ID$1 = "kg/space-after-question-or-exclamation";
|
|
1958
|
+
const MESSAGES$1 = {
|
|
1959
1959
|
default: "感嘆符または疑問符の直後には全角スペースか閉じ括弧が必要です",
|
|
1960
1960
|
"space-width": "感嘆符または疑問符の直後の空白は全角スペース1字にしてください",
|
|
1961
1961
|
"before-closing-bracket": "閉じ括弧の直前に空白を置くことはできません"
|
|
@@ -1971,8 +1971,8 @@ const MARKS = /[?!]+/gu;
|
|
|
1971
1971
|
const spaceAfterQuestionOrExclamationRule = () => ({
|
|
1972
1972
|
kind: "parsed",
|
|
1973
1973
|
meta: {
|
|
1974
|
-
id: RULE_ID,
|
|
1975
|
-
messages: MESSAGES
|
|
1974
|
+
id: RULE_ID$1,
|
|
1975
|
+
messages: MESSAGES$1
|
|
1976
1976
|
},
|
|
1977
1977
|
check: (manuscript, context) => {
|
|
1978
1978
|
const report = (start, end, messageId) => {
|
|
@@ -2000,22 +2000,74 @@ const spaceAfterQuestionOrExclamationRule = () => ({
|
|
|
2000
2000
|
});
|
|
2001
2001
|
//#endregion
|
|
2002
2002
|
//#region src/proofreading/rules/variant-character.ts
|
|
2003
|
+
const RULE_ID = "kg/variant-character";
|
|
2004
|
+
const MESSAGES = {
|
|
2005
|
+
default: "異体字または字形選択子が使われています",
|
|
2006
|
+
"with-suggestion": "異体字または字形選択子が使われています。「{{ suggestion }}」ではありませんか?"
|
|
2007
|
+
};
|
|
2008
|
+
/**
|
|
2009
|
+
* Mongolian free variation selectors, variation selectors (incl. emoji presentation), IVSes: all
|
|
2010
|
+
* combine with a preceding base character rather than standing on their own.
|
|
2011
|
+
*/
|
|
2012
|
+
function isSelector(codePoint) {
|
|
2013
|
+
return codePoint >= 6155 && codePoint <= 6157 || codePoint === 6159 || codePoint >= 65024 && codePoint <= 65039 || codePoint >= 917760 && codePoint <= 917999;
|
|
2014
|
+
}
|
|
2003
2015
|
/**
|
|
2004
|
-
*
|
|
2016
|
+
* CJK compatibility ideographs stand alone; each has a canonical unified form reachable via NFKC.
|
|
2005
2017
|
*/
|
|
2018
|
+
function isCompatibilityIdeograph(codePoint) {
|
|
2019
|
+
return codePoint >= 63744 && codePoint <= 64255 || codePoint >= 194560 && codePoint <= 195103;
|
|
2020
|
+
}
|
|
2006
2021
|
function isVariantCharacter(character) {
|
|
2007
2022
|
const codePoint = character.codePointAt(0);
|
|
2008
2023
|
if (codePoint === void 0) return false;
|
|
2009
|
-
return codePoint
|
|
2024
|
+
return isSelector(codePoint) || isCompatibilityIdeograph(codePoint);
|
|
2025
|
+
}
|
|
2026
|
+
/**
|
|
2027
|
+
* The plain form a reader would expect: the selector stripped away, or the compatibility
|
|
2028
|
+
* ideograph's canonical unified form. Undefined when that plain form is identical to the original,
|
|
2029
|
+
* since NFKC does not touch selectors and a suggestion equal to the input helps no one.
|
|
2030
|
+
*/
|
|
2031
|
+
function suggestPlainForm(segment) {
|
|
2032
|
+
const withoutSelectors = Array.from(segment).filter((character) => {
|
|
2033
|
+
const codePoint = character.codePointAt(0);
|
|
2034
|
+
return codePoint !== void 0 && !isSelector(codePoint);
|
|
2035
|
+
}).join("");
|
|
2036
|
+
if (withoutSelectors === "") return void 0;
|
|
2037
|
+
const normalized = Array.from(withoutSelectors).map((character) => {
|
|
2038
|
+
const codePoint = character.codePointAt(0);
|
|
2039
|
+
return codePoint !== void 0 && isCompatibilityIdeograph(codePoint) ? character.normalize("NFKC") : character;
|
|
2040
|
+
}).join("");
|
|
2041
|
+
return normalized === segment ? void 0 : normalized;
|
|
2010
2042
|
}
|
|
2011
2043
|
/**
|
|
2012
2044
|
* Scans the source rather than the display text: notation removal must not hide a variant.
|
|
2013
2045
|
*/
|
|
2014
|
-
const variantCharacterRule = () =>
|
|
2015
|
-
|
|
2016
|
-
|
|
2017
|
-
|
|
2018
|
-
|
|
2046
|
+
const variantCharacterRule = () => ({
|
|
2047
|
+
kind: "parsed",
|
|
2048
|
+
meta: {
|
|
2049
|
+
id: RULE_ID,
|
|
2050
|
+
messages: MESSAGES
|
|
2051
|
+
},
|
|
2052
|
+
check: (manuscript, context) => {
|
|
2053
|
+
for (const { index, segment } of graphemeSegmenter.segment(manuscript.source)) {
|
|
2054
|
+
if (!Array.from(segment).some(isVariantCharacter)) continue;
|
|
2055
|
+
const range = sourceRange(manuscript, {
|
|
2056
|
+
start: index,
|
|
2057
|
+
end: index + segment.length
|
|
2058
|
+
});
|
|
2059
|
+
const suggestion = suggestPlainForm(segment);
|
|
2060
|
+
if (suggestion === void 0) context.report({
|
|
2061
|
+
range,
|
|
2062
|
+
messageId: "default"
|
|
2063
|
+
});
|
|
2064
|
+
else context.report({
|
|
2065
|
+
range,
|
|
2066
|
+
messageId: "with-suggestion",
|
|
2067
|
+
data: { suggestion }
|
|
2068
|
+
});
|
|
2069
|
+
}
|
|
2070
|
+
}
|
|
2019
2071
|
});
|
|
2020
2072
|
//#endregion
|
|
2021
2073
|
//#region src/proofreading/rules/default-rules.ts
|