@termdock/twlint 1.0.0 → 1.0.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/README.md +176 -63
- package/dist/cli.d.ts.map +1 -1
- package/dist/cli.js +49 -10
- package/dist/cli.js.map +1 -1
- package/dist/core/config-schema.d.ts +1 -0
- package/dist/core/config-schema.d.ts.map +1 -1
- package/dist/core/config-schema.js +33 -7
- package/dist/core/config-schema.js.map +1 -1
- package/dist/core/dictionary-loading-strategies.d.ts +45 -0
- package/dist/core/dictionary-loading-strategies.d.ts.map +1 -0
- package/dist/core/dictionary-loading-strategies.js +75 -0
- package/dist/core/dictionary-loading-strategies.js.map +1 -0
- package/dist/core/dictionary-manager.d.ts +2 -1
- package/dist/core/dictionary-manager.d.ts.map +1 -1
- package/dist/core/dictionary-manager.js +51 -16
- package/dist/core/dictionary-manager.js.map +1 -1
- package/dist/core/linter.d.ts +2 -6
- package/dist/core/linter.d.ts.map +1 -1
- package/dist/core/linter.js +82 -58
- package/dist/core/linter.js.map +1 -1
- package/dist/core/lru-cache.d.ts +18 -0
- package/dist/core/lru-cache.d.ts.map +1 -0
- package/dist/core/lru-cache.js +57 -0
- package/dist/core/lru-cache.js.map +1 -0
- package/dist/core/matching/match-strategies.d.ts +19 -11
- package/dist/core/matching/match-strategies.d.ts.map +1 -1
- package/dist/core/matching/match-strategies.js +44 -74
- package/dist/core/matching/match-strategies.js.map +1 -1
- package/dist/core/rules/mainland-terms.d.ts +3 -1
- package/dist/core/rules/mainland-terms.d.ts.map +1 -1
- package/dist/core/rules/mainland-terms.js +25 -4
- package/dist/core/rules/mainland-terms.js.map +1 -1
- package/dist/dictionaries/academic.json +242 -22
- package/dist/dictionaries/ai-emerging-tech.json +3209 -0
- package/dist/dictionaries/business-finance.json +3449 -0
- package/dist/dictionaries/core.json +2902 -248
- package/dist/dictionaries/hardware-3c.json +2649 -0
- package/dist/dictionaries/index.json +70 -8
- package/dist/dictionaries/network-cloud.json +2953 -0
- package/dist/dictionaries/operating-system.json +2889 -0
- package/dist/dictionaries/social-media.json +2833 -0
- package/dist/dictionaries/software-development.json +3809 -0
- package/dist/dictionaries/user-interface.json +3225 -0
- package/dist/formatters/stylish.d.ts.map +1 -1
- package/dist/formatters/stylish.js +5 -15
- package/dist/formatters/stylish.js.map +1 -1
- package/dist/types.d.ts +20 -8
- package/dist/types.d.ts.map +1 -1
- package/dist/utils/error-utils.d.ts +9 -0
- package/dist/utils/error-utils.d.ts.map +1 -0
- package/dist/utils/error-utils.js +15 -0
- package/dist/utils/error-utils.js.map +1 -0
- package/package.json +5 -5
|
@@ -1,19 +1,26 @@
|
|
|
1
|
-
import type { MatchStrategy, MatchResult, ContextRule } from '../../types.js';
|
|
2
|
-
|
|
3
|
-
|
|
1
|
+
import type { MatchStrategy, MatchResult, ContextRule, MatchType } from '../../types.js';
|
|
2
|
+
/**
|
|
3
|
+
* 匹配策略基類 - 統一上下文驗證邏輯
|
|
4
|
+
*/
|
|
5
|
+
declare abstract class BaseMatchStrategy implements MatchStrategy {
|
|
6
|
+
abstract readonly name: MatchType;
|
|
7
|
+
abstract match(text: string, term: string, context?: ContextRule): MatchResult[];
|
|
8
|
+
protected validateContext(text: string, term: string, index: number, context?: ContextRule): boolean;
|
|
9
|
+
protected getContextRange(): number;
|
|
10
|
+
protected escapeRegExp(string: string): string;
|
|
11
|
+
}
|
|
12
|
+
export declare class ExactMatchStrategy extends BaseMatchStrategy {
|
|
13
|
+
readonly name: "exact";
|
|
4
14
|
match(text: string, term: string, context?: ContextRule): MatchResult[];
|
|
5
|
-
private isValidMatch;
|
|
6
15
|
}
|
|
7
|
-
export declare class WordBoundaryStrategy
|
|
8
|
-
name: "word_boundary";
|
|
16
|
+
export declare class WordBoundaryStrategy extends BaseMatchStrategy {
|
|
17
|
+
readonly name: "word_boundary";
|
|
9
18
|
match(text: string, term: string, context?: ContextRule): MatchResult[];
|
|
10
|
-
private isValidMatch;
|
|
11
|
-
private escapeRegExp;
|
|
12
19
|
}
|
|
13
|
-
export declare class ContextSensitiveStrategy
|
|
14
|
-
name: "context_sensitive";
|
|
20
|
+
export declare class ContextSensitiveStrategy extends BaseMatchStrategy {
|
|
21
|
+
readonly name: "context_sensitive";
|
|
15
22
|
match(text: string, term: string, context?: ContextRule): MatchResult[];
|
|
16
|
-
|
|
23
|
+
protected getContextRange(): number;
|
|
17
24
|
}
|
|
18
25
|
export declare class MatchStrategyRegistry {
|
|
19
26
|
private strategies;
|
|
@@ -23,4 +30,5 @@ export declare class MatchStrategyRegistry {
|
|
|
23
30
|
getStrategy(name: string): MatchStrategy | undefined;
|
|
24
31
|
getAllStrategies(): MatchStrategy[];
|
|
25
32
|
}
|
|
33
|
+
export {};
|
|
26
34
|
//# sourceMappingURL=match-strategies.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"match-strategies.d.ts","sourceRoot":"","sources":["../../../src/core/matching/match-strategies.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,WAAW,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAA;
|
|
1
|
+
{"version":3,"file":"match-strategies.d.ts","sourceRoot":"","sources":["../../../src/core/matching/match-strategies.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,WAAW,EAAE,WAAW,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAA;AAExF;;GAEG;AACH,uBAAe,iBAAkB,YAAW,aAAa;IACvD,QAAQ,CAAC,QAAQ,CAAC,IAAI,EAAE,SAAS,CAAA;IACjC,QAAQ,CAAC,KAAK,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,WAAW,GAAG,WAAW,EAAE;IAEhF,SAAS,CAAC,eAAe,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,WAAW,GAAG,OAAO;IAgCpG,SAAS,CAAC,eAAe,IAAI,MAAM;IAInC,SAAS,CAAC,YAAY,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM;CAG/C;AAED,qBAAa,kBAAmB,SAAQ,iBAAiB;IACvD,QAAQ,CAAC,IAAI,EAAG,OAAO,CAAS;IAEhC,KAAK,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,WAAW,GAAG,WAAW,EAAE;CA0BxE;AAED,qBAAa,oBAAqB,SAAQ,iBAAiB;IACzD,QAAQ,CAAC,IAAI,EAAG,eAAe,CAAS;IAExC,KAAK,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,WAAW,GAAG,WAAW,EAAE;CA0BxE;AAED,qBAAa,wBAAyB,SAAQ,iBAAiB;IAC7D,QAAQ,CAAC,IAAI,EAAG,mBAAmB,CAAS;IAE5C,KAAK,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,WAAW,GAAG,WAAW,EAAE;IA+BvE,SAAS,CAAC,eAAe,IAAI,MAAM;CAGpC;AAED,qBAAa,qBAAqB;IAChC,OAAO,CAAC,UAAU,CAAmC;;IAMrD,OAAO,CAAC,gBAAgB;IAMxB,QAAQ,CAAC,QAAQ,EAAE,aAAa,GAAG,IAAI;IAIvC,WAAW,CAAC,IAAI,EAAE,MAAM,GAAG,aAAa,GAAG,SAAS;IAIpD,gBAAgB,IAAI,aAAa,EAAE;CAGpC"}
|
|
@@ -1,31 +1,13 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
while (true) {
|
|
7
|
-
const index = text.indexOf(term, startIndex);
|
|
8
|
-
if (index === -1)
|
|
9
|
-
break;
|
|
10
|
-
if (this.isValidMatch(text, term, index, context)) {
|
|
11
|
-
results.push({
|
|
12
|
-
term,
|
|
13
|
-
replacement: '', // Will be filled by caller
|
|
14
|
-
start: index,
|
|
15
|
-
end: index + term.length,
|
|
16
|
-
confidence: 1.0,
|
|
17
|
-
rule: 'exact-match'
|
|
18
|
-
});
|
|
19
|
-
}
|
|
20
|
-
startIndex = index + 1;
|
|
21
|
-
}
|
|
22
|
-
return results;
|
|
23
|
-
}
|
|
24
|
-
isValidMatch(text, term, index, context) {
|
|
1
|
+
/**
|
|
2
|
+
* 匹配策略基類 - 統一上下文驗證邏輯
|
|
3
|
+
*/
|
|
4
|
+
class BaseMatchStrategy {
|
|
5
|
+
validateContext(text, term, index, context) {
|
|
25
6
|
if (!context)
|
|
26
7
|
return true;
|
|
27
|
-
const
|
|
28
|
-
const
|
|
8
|
+
const contextRange = this.getContextRange();
|
|
9
|
+
const beforeText = text.substring(Math.max(0, index - contextRange), index);
|
|
10
|
+
const afterText = text.substring(index + term.length, Math.min(text.length, index + term.length + contextRange));
|
|
29
11
|
// Check exclude patterns
|
|
30
12
|
if (context.exclude) {
|
|
31
13
|
const surroundingText = beforeText + term + afterText;
|
|
@@ -49,8 +31,38 @@ export class ExactMatchStrategy {
|
|
|
49
31
|
}
|
|
50
32
|
return true;
|
|
51
33
|
}
|
|
34
|
+
getContextRange() {
|
|
35
|
+
return 20; // 預設上下文檢查範圍
|
|
36
|
+
}
|
|
37
|
+
escapeRegExp(string) {
|
|
38
|
+
return string.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
export class ExactMatchStrategy extends BaseMatchStrategy {
|
|
42
|
+
name = 'exact';
|
|
43
|
+
match(text, term, context) {
|
|
44
|
+
const results = [];
|
|
45
|
+
let startIndex = 0;
|
|
46
|
+
while (true) {
|
|
47
|
+
const index = text.indexOf(term, startIndex);
|
|
48
|
+
if (index === -1)
|
|
49
|
+
break;
|
|
50
|
+
if (this.validateContext(text, term, index, context)) {
|
|
51
|
+
results.push({
|
|
52
|
+
term,
|
|
53
|
+
replacement: '', // Will be filled by caller
|
|
54
|
+
start: index,
|
|
55
|
+
end: index + term.length,
|
|
56
|
+
confidence: 1.0,
|
|
57
|
+
rule: 'exact-match'
|
|
58
|
+
});
|
|
59
|
+
}
|
|
60
|
+
startIndex = index + 1;
|
|
61
|
+
}
|
|
62
|
+
return results;
|
|
63
|
+
}
|
|
52
64
|
}
|
|
53
|
-
export class WordBoundaryStrategy {
|
|
65
|
+
export class WordBoundaryStrategy extends BaseMatchStrategy {
|
|
54
66
|
name = 'word_boundary';
|
|
55
67
|
match(text, term, context) {
|
|
56
68
|
const results = [];
|
|
@@ -60,7 +72,7 @@ export class WordBoundaryStrategy {
|
|
|
60
72
|
let match;
|
|
61
73
|
while ((match = chineseWordPattern.exec(text)) !== null) {
|
|
62
74
|
const index = match.index;
|
|
63
|
-
if (this.
|
|
75
|
+
if (this.validateContext(text, term, index, context)) {
|
|
64
76
|
results.push({
|
|
65
77
|
term,
|
|
66
78
|
replacement: '', // Will be filled by caller
|
|
@@ -73,27 +85,8 @@ export class WordBoundaryStrategy {
|
|
|
73
85
|
}
|
|
74
86
|
return results;
|
|
75
87
|
}
|
|
76
|
-
isValidMatch(text, term, index, context) {
|
|
77
|
-
if (!context)
|
|
78
|
-
return true;
|
|
79
|
-
const beforeText = text.substring(Math.max(0, index - 20), index);
|
|
80
|
-
const afterText = text.substring(index + term.length, Math.min(text.length, index + term.length + 20));
|
|
81
|
-
// Check exclude patterns
|
|
82
|
-
if (context.exclude) {
|
|
83
|
-
const surroundingText = beforeText + term + afterText;
|
|
84
|
-
for (const excludePattern of context.exclude) {
|
|
85
|
-
if (surroundingText.includes(excludePattern)) {
|
|
86
|
-
return false;
|
|
87
|
-
}
|
|
88
|
-
}
|
|
89
|
-
}
|
|
90
|
-
return true;
|
|
91
|
-
}
|
|
92
|
-
escapeRegExp(string) {
|
|
93
|
-
return string.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
|
|
94
|
-
}
|
|
95
88
|
}
|
|
96
|
-
export class ContextSensitiveStrategy {
|
|
89
|
+
export class ContextSensitiveStrategy extends BaseMatchStrategy {
|
|
97
90
|
name = 'context_sensitive';
|
|
98
91
|
match(text, term, context) {
|
|
99
92
|
if (!context || (!context.before && !context.after)) {
|
|
@@ -106,7 +99,7 @@ export class ContextSensitiveStrategy {
|
|
|
106
99
|
const index = text.indexOf(term, startIndex);
|
|
107
100
|
if (index === -1)
|
|
108
101
|
break;
|
|
109
|
-
if (this.
|
|
102
|
+
if (this.validateContext(text, term, index, context)) {
|
|
110
103
|
results.push({
|
|
111
104
|
term,
|
|
112
105
|
replacement: '', // Will be filled by caller
|
|
@@ -120,31 +113,8 @@ export class ContextSensitiveStrategy {
|
|
|
120
113
|
}
|
|
121
114
|
return results;
|
|
122
115
|
}
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
const afterText = text.substring(index + term.length, Math.min(text.length, index + term.length + 50));
|
|
126
|
-
// Check exclude patterns first
|
|
127
|
-
if (context.exclude) {
|
|
128
|
-
const surroundingText = beforeText + term + afterText;
|
|
129
|
-
for (const excludePattern of context.exclude) {
|
|
130
|
-
if (surroundingText.includes(excludePattern)) {
|
|
131
|
-
return false;
|
|
132
|
-
}
|
|
133
|
-
}
|
|
134
|
-
}
|
|
135
|
-
// Must match before context if specified
|
|
136
|
-
if (context.before) {
|
|
137
|
-
const hasValidBefore = context.before.some(pattern => beforeText.includes(pattern));
|
|
138
|
-
if (!hasValidBefore)
|
|
139
|
-
return false;
|
|
140
|
-
}
|
|
141
|
-
// Must match after context if specified
|
|
142
|
-
if (context.after) {
|
|
143
|
-
const hasValidAfter = context.after.some(pattern => afterText.includes(pattern));
|
|
144
|
-
if (!hasValidAfter)
|
|
145
|
-
return false;
|
|
146
|
-
}
|
|
147
|
-
return true;
|
|
116
|
+
getContextRange() {
|
|
117
|
+
return 50; // 語境敏感策略需要更大的檢查範圍
|
|
148
118
|
}
|
|
149
119
|
}
|
|
150
120
|
export class MatchStrategyRegistry {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"match-strategies.js","sourceRoot":"","sources":["../../../src/core/matching/match-strategies.ts"],"names":[],"mappings":"AAEA
|
|
1
|
+
{"version":3,"file":"match-strategies.js","sourceRoot":"","sources":["../../../src/core/matching/match-strategies.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,9 +1,11 @@
|
|
|
1
|
-
import type { Rule, Issue } from '../../types.js';
|
|
1
|
+
import type { Rule, Issue, TextProcessingContext } from '../../types.js';
|
|
2
2
|
import type { DictionaryManager } from '../dictionary-manager.js';
|
|
3
3
|
export declare class MainlandTermsRule implements Rule {
|
|
4
4
|
readonly name = "mainland-terms";
|
|
5
5
|
private dictManager;
|
|
6
|
+
private converter;
|
|
6
7
|
constructor(dictManager: DictionaryManager);
|
|
8
|
+
preprocess(text: string): Promise<TextProcessingContext>;
|
|
7
9
|
check(text: string): Promise<Issue[]>;
|
|
8
10
|
fix(text: string): Promise<string>;
|
|
9
11
|
private getLineInfo;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"mainland-terms.d.ts","sourceRoot":"","sources":["../../../src/core/rules/mainland-terms.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAE,KAAK,EAAE,MAAM,gBAAgB,CAAA;
|
|
1
|
+
{"version":3,"file":"mainland-terms.d.ts","sourceRoot":"","sources":["../../../src/core/rules/mainland-terms.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAE,KAAK,EAAE,qBAAqB,EAAE,MAAM,gBAAgB,CAAA;AACxE,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,0BAA0B,CAAA;AAIjE,qBAAa,iBAAkB,YAAW,IAAI;IAC5C,QAAQ,CAAC,IAAI,oBAAmB;IAChC,OAAO,CAAC,WAAW,CAAmB;IACtC,OAAO,CAAC,SAAS,CAA8B;gBAEnC,WAAW,EAAE,iBAAiB;IAKpC,UAAU,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,qBAAqB,CAAC;IAYxD,KAAK,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,KAAK,EAAE,CAAC;IA2BrC,GAAG,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;IAoBxC,OAAO,CAAC,WAAW;CAOpB"}
|
|
@@ -1,22 +1,41 @@
|
|
|
1
|
+
import { PositionMapper } from '../position-mapper.js';
|
|
2
|
+
import { Converter } from 'opencc-js';
|
|
1
3
|
export class MainlandTermsRule {
|
|
2
4
|
name = 'mainland-terms';
|
|
3
5
|
dictManager;
|
|
6
|
+
converter;
|
|
4
7
|
constructor(dictManager) {
|
|
5
8
|
this.dictManager = dictManager;
|
|
9
|
+
this.converter = Converter({ from: 'cn', to: 'tw' });
|
|
10
|
+
}
|
|
11
|
+
async preprocess(text) {
|
|
12
|
+
// Convert simplified to traditional for better matching
|
|
13
|
+
const convertedText = this.converter(text);
|
|
14
|
+
const positionMapper = new PositionMapper(text, convertedText);
|
|
15
|
+
return {
|
|
16
|
+
originalText: text,
|
|
17
|
+
processedText: convertedText,
|
|
18
|
+
positionMapper
|
|
19
|
+
};
|
|
6
20
|
}
|
|
7
21
|
async check(text) {
|
|
8
22
|
const issues = [];
|
|
9
23
|
const matches = this.dictManager.findMatches(text);
|
|
10
24
|
for (const match of matches) {
|
|
11
25
|
const lineInfo = this.getLineInfo(text, match.start);
|
|
26
|
+
// 根據 autofix_safe 決定訊息和可修復性
|
|
27
|
+
const isContextSensitive = match.rule.includes('context_sensitive');
|
|
28
|
+
const message = isContextSensitive
|
|
29
|
+
? `可能的大陸用語 '${match.term}' 建議使用臺灣用語 '${match.replacement}' (請確認語境)`
|
|
30
|
+
: `大陸用語 '${match.term}' 建議使用臺灣用語 '${match.replacement}'`;
|
|
12
31
|
issues.push({
|
|
13
32
|
line: lineInfo.line,
|
|
14
33
|
column: lineInfo.column,
|
|
15
|
-
message
|
|
16
|
-
severity: 'warning',
|
|
34
|
+
message,
|
|
35
|
+
severity: match.autofix_safe ? 'warning' : 'info',
|
|
17
36
|
rule: this.name,
|
|
18
37
|
suggestions: [match.replacement],
|
|
19
|
-
fixable:
|
|
38
|
+
fixable: match.autofix_safe || false
|
|
20
39
|
});
|
|
21
40
|
}
|
|
22
41
|
return issues;
|
|
@@ -24,8 +43,10 @@ export class MainlandTermsRule {
|
|
|
24
43
|
async fix(text) {
|
|
25
44
|
let fixedText = text;
|
|
26
45
|
const matches = this.dictManager.findMatches(text);
|
|
46
|
+
// 只修正標記為安全的詞彙
|
|
47
|
+
const safeMatches = matches.filter(match => match.autofix_safe);
|
|
27
48
|
// Sort by position (from end to start) to avoid offset issues
|
|
28
|
-
const sortedMatches =
|
|
49
|
+
const sortedMatches = safeMatches.sort((a, b) => b.start - a.start);
|
|
29
50
|
for (const match of sortedMatches) {
|
|
30
51
|
// Replace using precise position information
|
|
31
52
|
fixedText = fixedText.substring(0, match.start) +
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"mainland-terms.js","sourceRoot":"","sources":["../../../src/core/rules/mainland-terms.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"mainland-terms.js","sourceRoot":"","sources":["../../../src/core/rules/mainland-terms.ts"],"names":[],"mappings":"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"}
|