@termdock/twlint 1.0.3 → 1.2.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 +104 -17
- package/dist/cli.d.ts.map +1 -1
- package/dist/cli.js +18 -15
- package/dist/cli.js.map +1 -1
- package/dist/core/config-loader.d.ts +2 -2
- package/dist/core/config-loader.d.ts.map +1 -1
- package/dist/core/config-loader.js +1 -1
- package/dist/core/config-matcher.d.ts +58 -0
- package/dist/core/config-matcher.d.ts.map +1 -0
- package/dist/core/config-matcher.js +236 -0
- package/dist/core/config-matcher.js.map +1 -0
- package/dist/core/config-schema.d.ts +2 -1
- package/dist/core/config-schema.d.ts.map +1 -1
- package/dist/core/config-schema.js +30 -26
- package/dist/core/config-schema.js.map +1 -1
- package/dist/core/dictionary-loading-strategies.d.ts +1 -1
- package/dist/core/dictionary-loading-strategies.js +1 -1
- package/dist/core/dictionary-manager.d.ts +1 -1
- package/dist/core/dictionary-manager.d.ts.map +1 -1
- package/dist/core/dictionary-manager.js +76 -24
- package/dist/core/dictionary-manager.js.map +1 -1
- package/dist/core/ignore-file-loader.d.ts +29 -0
- package/dist/core/ignore-file-loader.d.ts.map +1 -0
- package/dist/core/ignore-file-loader.js +74 -0
- package/dist/core/ignore-file-loader.js.map +1 -0
- package/dist/core/linter.d.ts +42 -5
- package/dist/core/linter.d.ts.map +1 -1
- package/dist/core/linter.js +129 -38
- package/dist/core/linter.js.map +1 -1
- package/dist/dictionaries/academic.json +1 -1
- package/dist/dictionaries/ai-emerging-tech.json +1 -1
- package/dist/dictionaries/business-finance.json +1 -1
- package/dist/dictionaries/core.json +386 -2
- package/dist/dictionaries/hardware-3c.json +1 -1
- package/dist/dictionaries/index.json +4 -4
- package/dist/dictionaries/network-cloud.json +1 -1
- package/dist/dictionaries/operating-system.json +1 -1
- package/dist/dictionaries/social-media.json +1 -1
- package/dist/dictionaries/software-development.json +34 -2
- package/dist/dictionaries/user-interface.json +1 -1
- package/dist/types.d.ts +2 -0
- package/dist/types.d.ts.map +1 -1
- package/package.json +2 -2
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config-matcher.js","sourceRoot":"","sources":["../../src/core/config-matcher.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
export interface TWLintConfigRule {
|
|
2
2
|
files?: string[];
|
|
3
|
+
ignores?: string[];
|
|
3
4
|
dictionaries?: string[];
|
|
4
5
|
domains?: string[];
|
|
5
6
|
rules?: Record<string, 'error' | 'warning' | 'info' | 'off'>;
|
|
@@ -8,6 +9,6 @@ export type TWLintConfigArray = TWLintConfigRule[];
|
|
|
8
9
|
export type TWLintConfigSingle = TWLintConfigRule;
|
|
9
10
|
export type TWLintUserConfig = TWLintConfigSingle | TWLintConfigArray;
|
|
10
11
|
export declare const DEFAULT_CONFIG: TWLintConfigSingle;
|
|
11
|
-
export declare function validateConfig(config: unknown):
|
|
12
|
+
export declare function validateConfig(config: unknown): TWLintUserConfig;
|
|
12
13
|
export declare function createSampleConfig(): string;
|
|
13
14
|
//# sourceMappingURL=config-schema.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"config-schema.d.ts","sourceRoot":"","sources":["../../src/core/config-schema.ts"],"names":[],"mappings":"AAEA,MAAM,WAAW,gBAAgB;IAC/B,KAAK,CAAC,EAAE,MAAM,EAAE,CAAA;IAChB,YAAY,CAAC,EAAE,MAAM,EAAE,CAAA;IACvB,OAAO,CAAC,EAAE,MAAM,EAAE,CAAA;IAClB,KAAK,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,GAAG,SAAS,GAAG,MAAM,GAAG,KAAK,CAAC,CAAA;CAC7D;AAED,MAAM,MAAM,iBAAiB,GAAG,gBAAgB,EAAE,CAAA;AAClD,MAAM,MAAM,kBAAkB,GAAG,gBAAgB,CAAA;AAGjD,MAAM,MAAM,gBAAgB,GAAG,kBAAkB,GAAG,iBAAiB,CAAA;AAErE,eAAO,MAAM,cAAc,EAAE,kBAO5B,CAAA;AAED,wBAAgB,cAAc,CAAC,MAAM,EAAE,OAAO,GAAG,
|
|
1
|
+
{"version":3,"file":"config-schema.d.ts","sourceRoot":"","sources":["../../src/core/config-schema.ts"],"names":[],"mappings":"AAEA,MAAM,WAAW,gBAAgB;IAC/B,KAAK,CAAC,EAAE,MAAM,EAAE,CAAA;IAChB,OAAO,CAAC,EAAE,MAAM,EAAE,CAAA;IAClB,YAAY,CAAC,EAAE,MAAM,EAAE,CAAA;IACvB,OAAO,CAAC,EAAE,MAAM,EAAE,CAAA;IAClB,KAAK,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,GAAG,SAAS,GAAG,MAAM,GAAG,KAAK,CAAC,CAAA;CAC7D;AAED,MAAM,MAAM,iBAAiB,GAAG,gBAAgB,EAAE,CAAA;AAClD,MAAM,MAAM,kBAAkB,GAAG,gBAAgB,CAAA;AAGjD,MAAM,MAAM,gBAAgB,GAAG,kBAAkB,GAAG,iBAAiB,CAAA;AAErE,eAAO,MAAM,cAAc,EAAE,kBAO5B,CAAA;AAED,wBAAgB,cAAc,CAAC,MAAM,EAAE,OAAO,GAAG,gBAAgB,CAYhE;AAED,wBAAgB,kBAAkB,IAAI,MAAM,CAwE3C"}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
// TWLint
|
|
1
|
+
// TWLint 設定檔案結構定義和驗證
|
|
2
2
|
export const DEFAULT_CONFIG = {
|
|
3
3
|
files: ['**/*.md', '**/*.txt'],
|
|
4
4
|
dictionaries: ['core'],
|
|
@@ -11,41 +11,37 @@ export function validateConfig(config) {
|
|
|
11
11
|
if (!config || typeof config !== 'object') {
|
|
12
12
|
return DEFAULT_CONFIG;
|
|
13
13
|
}
|
|
14
|
-
//
|
|
14
|
+
// 如果是陣列,保持陣列形式(ESLint flat config 風格)
|
|
15
15
|
if (Array.isArray(config)) {
|
|
16
|
-
return
|
|
16
|
+
return config;
|
|
17
17
|
}
|
|
18
|
-
//
|
|
19
|
-
return
|
|
20
|
-
}
|
|
21
|
-
function mergeConfigs(configs) {
|
|
22
|
-
let merged = { ...DEFAULT_CONFIG };
|
|
23
|
-
for (const config of configs) {
|
|
24
|
-
if (config && typeof config === 'object') {
|
|
25
|
-
merged = mergeConfig(merged, config);
|
|
26
|
-
}
|
|
27
|
-
}
|
|
28
|
-
return merged;
|
|
29
|
-
}
|
|
30
|
-
function mergeConfig(defaultConfig, userConfig) {
|
|
31
|
-
return {
|
|
32
|
-
files: userConfig.files || defaultConfig.files,
|
|
33
|
-
dictionaries: userConfig.dictionaries || defaultConfig.dictionaries,
|
|
34
|
-
domains: userConfig.domains || defaultConfig.domains, // 保留 domains 配置
|
|
35
|
-
rules: {
|
|
36
|
-
...defaultConfig.rules,
|
|
37
|
-
...userConfig.rules
|
|
38
|
-
}
|
|
39
|
-
};
|
|
18
|
+
// 單一設定物件
|
|
19
|
+
return config;
|
|
40
20
|
}
|
|
41
21
|
export function createSampleConfig() {
|
|
42
|
-
return `// TWLint
|
|
22
|
+
return `// TWLint 設定檔案
|
|
43
23
|
// 專注於核心功能:簡繁轉換 + 大陸用語檢測
|
|
44
24
|
|
|
45
25
|
export default [
|
|
26
|
+
// Global ignores - 全域忽略模式(只有 ignores 屬性時視為全域)
|
|
27
|
+
//
|
|
28
|
+
// 注意:以下檔案已被系統鐵律保護,無需額外設定:
|
|
29
|
+
// - 設定檔案:.gitignore, .dockerignore, .env*, 等
|
|
30
|
+
// - 版本控制:.git/, .svn/, node_modules/
|
|
31
|
+
// - 建構輸出:dist/, build/, .next/
|
|
32
|
+
// - 日誌檔案:*.log, *.tmp
|
|
33
|
+
{
|
|
34
|
+
ignores: [
|
|
35
|
+
// 專案特定的忽略模式
|
|
36
|
+
"**/test-*.md",
|
|
37
|
+
"**/draft-*.md"
|
|
38
|
+
]
|
|
39
|
+
},
|
|
40
|
+
|
|
46
41
|
{
|
|
47
42
|
// 文件檔案:完整檢查
|
|
48
43
|
files: ["**/*.md", "**/*.txt"],
|
|
44
|
+
ignores: ["**/README.md"], // 排除 README
|
|
49
45
|
domains: ["software-development", "user-interface"],
|
|
50
46
|
rules: {
|
|
51
47
|
"simplified-chars": "error", // 簡體字檢測(自動修復)
|
|
@@ -61,6 +57,14 @@ export default [
|
|
|
61
57
|
"mainland-terms": "warning" // UI 文字中的大陸用語提醒
|
|
62
58
|
}
|
|
63
59
|
},
|
|
60
|
+
{
|
|
61
|
+
// 測試檔案:放寬規則
|
|
62
|
+
files: ["tests/**/*.{js,ts,md}"],
|
|
63
|
+
rules: {
|
|
64
|
+
"simplified-chars": "error",
|
|
65
|
+
"mainland-terms": "off" // 測試檔案允許大陸用語
|
|
66
|
+
}
|
|
67
|
+
},
|
|
64
68
|
{
|
|
65
69
|
// 商業文件:更嚴格的檢查
|
|
66
70
|
files: ["docs/business/**/*.md"],
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"config-schema.js","sourceRoot":"","sources":["../../src/core/config-schema.ts"],"names":[],"mappings":"AAAA,qBAAqB;
|
|
1
|
+
{"version":3,"file":"config-schema.js","sourceRoot":"","sources":["../../src/core/config-schema.ts"],"names":[],"mappings":"AAAA,qBAAqB;AAgBrB,MAAM,CAAC,MAAM,cAAc,GAAuB;IAChD,KAAK,EAAE,CAAC,SAAS,EAAE,UAAU,CAAC;IAC9B,YAAY,EAAE,CAAC,MAAM,CAAC;IACtB,KAAK,EAAE;QACL,kBAAkB,EAAE,OAAO;QAC3B,gBAAgB,EAAE,SAAS;KAC5B;CACF,CAAA;AAED,MAAM,UAAU,cAAc,CAAC,MAAe;IAC5C,IAAI,CAAC,MAAM,IAAI,OAAO,MAAM,KAAK,QAAQ,EAAE,CAAC;QAC1C,OAAO,cAAc,CAAA;IACvB,CAAC;IAED,sCAAsC;IACtC,IAAI,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE,CAAC;QAC1B,OAAO,MAA2B,CAAA;IACpC,CAAC;IAED,SAAS;IACT,OAAO,MAA4B,CAAA;AACrC,CAAC;AAED,MAAM,UAAU,kBAAkB;IAChC,OAAO;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;wBAsEe,CAAA;AACxB,CAAC"}
|
|
@@ -37,7 +37,7 @@ export declare class DeepDictStrategy implements DictLoadStrategy {
|
|
|
37
37
|
getDictionaries(config: TWLintConfig, manager: DictionaryManager): Promise<string[]>;
|
|
38
38
|
}
|
|
39
39
|
/**
|
|
40
|
-
*
|
|
40
|
+
* 策略工廠:根據設定選擇適當的策略
|
|
41
41
|
*/
|
|
42
42
|
export declare class DictLoadStrategyFactory {
|
|
43
43
|
static create(config: TWLintConfig, deep?: boolean): DictLoadStrategy;
|
|
@@ -6,7 +6,7 @@ export declare class DictionaryManager {
|
|
|
6
6
|
constructor(dictionariesPath?: string, maxCacheSize?: number);
|
|
7
7
|
loadDictionary(name: string): Promise<CompiledDict>;
|
|
8
8
|
findMatches(text: string): MatchResult[];
|
|
9
|
-
private
|
|
9
|
+
private addMatch;
|
|
10
10
|
scanAvailableDictionaries(): Promise<string[]>;
|
|
11
11
|
getLoadedDictionaries(): string[];
|
|
12
12
|
clearCache(): void;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"dictionary-manager.d.ts","sourceRoot":"","sources":["../../src/core/dictionary-manager.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,YAAY,EAAE,WAAW,EAAmB,MAAM,aAAa,CAAA;AAK7E,qBAAa,iBAAiB;IAC5B,OAAO,CAAC,KAAK,CAAyC;IACtD,OAAO,CAAC,QAAQ,CAAC,gBAAgB,CAAQ;IACzC,OAAO,CAAC,QAAQ,CAAC,gBAAgB,CAAuB;gBAE5C,gBAAgB,CAAC,EAAE,MAAM,EAAE,YAAY,CAAC,EAAE,MAAM;IActD,cAAc,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,YAAY,CAAC;IAiBzD,WAAW,CAAC,IAAI,EAAE,MAAM,GAAG,WAAW,EAAE;
|
|
1
|
+
{"version":3,"file":"dictionary-manager.d.ts","sourceRoot":"","sources":["../../src/core/dictionary-manager.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,YAAY,EAAE,WAAW,EAAmB,MAAM,aAAa,CAAA;AAK7E,qBAAa,iBAAiB;IAC5B,OAAO,CAAC,KAAK,CAAyC;IACtD,OAAO,CAAC,QAAQ,CAAC,gBAAgB,CAAQ;IACzC,OAAO,CAAC,QAAQ,CAAC,gBAAgB,CAAuB;gBAE5C,gBAAgB,CAAC,EAAE,MAAM,EAAE,YAAY,CAAC,EAAE,MAAM;IActD,cAAc,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,YAAY,CAAC;IAiBzD,WAAW,CAAC,IAAI,EAAE,MAAM,GAAG,WAAW,EAAE;IAgIxC,OAAO,CAAC,QAAQ;IAgBV,yBAAyB,IAAI,OAAO,CAAC,MAAM,EAAE,CAAC;IAepD,qBAAqB,IAAI,MAAM,EAAE;IAIjC,UAAU,IAAI,IAAI;IAKlB,wBAAwB,IAAI,MAAM,EAAE;CAIrC"}
|
|
@@ -38,7 +38,6 @@ export class DictionaryManager {
|
|
|
38
38
|
}
|
|
39
39
|
findMatches(text) {
|
|
40
40
|
const allMatches = [];
|
|
41
|
-
const processedRanges = new Map(); // 改為 Map 來追蹤最佳匹配
|
|
42
41
|
for (const dict of this.cache.values()) {
|
|
43
42
|
// 先處理所有基本詞彙匹配
|
|
44
43
|
const basicTerms = Object.keys(dict.lookup).filter(term => !term.includes('_'));
|
|
@@ -51,7 +50,7 @@ export class DictionaryManager {
|
|
|
51
50
|
continue;
|
|
52
51
|
const matches = strategy.match(text, term, entry.context);
|
|
53
52
|
for (const match of matches) {
|
|
54
|
-
this.
|
|
53
|
+
this.addMatch(allMatches, match, entry, dict.metadata.name);
|
|
55
54
|
}
|
|
56
55
|
// 對於語境敏感詞彙,同時檢查其變體
|
|
57
56
|
if (entry.match_type === 'context_sensitive') {
|
|
@@ -63,42 +62,95 @@ export class DictionaryManager {
|
|
|
63
62
|
continue;
|
|
64
63
|
const variantMatches = variantStrategy.match(text, term, variantEntry.context);
|
|
65
64
|
for (const match of variantMatches) {
|
|
66
|
-
this.
|
|
65
|
+
this.addMatch(allMatches, match, variantEntry, dict.metadata.name, true);
|
|
67
66
|
}
|
|
68
67
|
}
|
|
69
68
|
}
|
|
70
69
|
}
|
|
71
70
|
}
|
|
72
|
-
//
|
|
73
|
-
|
|
71
|
+
// 1. 排序:優先長度,其次信心度,最後位置
|
|
72
|
+
// Sort logic: Longest length > Higher confidence > Earlier position
|
|
73
|
+
allMatches.sort((a, b) => {
|
|
74
|
+
const lenA = a.end - a.start;
|
|
75
|
+
const lenB = b.end - b.start;
|
|
76
|
+
if (lenA !== lenB)
|
|
77
|
+
return lenB - lenA; // Longest first
|
|
74
78
|
if (Math.abs(a.confidence - b.confidence) > 0.01) {
|
|
75
|
-
return b.confidence - a.confidence;
|
|
79
|
+
return b.confidence - a.confidence; // Higher confidence first
|
|
76
80
|
}
|
|
77
|
-
return a.start - b.start;
|
|
81
|
+
return a.start - b.start; // Earlier position first
|
|
78
82
|
});
|
|
83
|
+
// 2. 去重:過濾掉與高優先級匹配重疊的結果
|
|
84
|
+
// Deduplication using Interval Merging (O(N log N) or O(N) since already sorted by length?)
|
|
85
|
+
// Actually, simply maintaining a list of disjoint intervals is enough.
|
|
86
|
+
// Since matches are sorted by Length DESC, we iterate and check if the current match
|
|
87
|
+
// overlaps with ANY already accepted match.
|
|
88
|
+
// To do this efficiently:
|
|
89
|
+
// We can use a simple boolean array if text is short, but text can be long.
|
|
90
|
+
// Better: Maintain a sorted list of accepted intervals [start, end).
|
|
91
|
+
// For each candidate, check if it overlaps with any interval in the list.
|
|
92
|
+
// Since we process in priority order, if it doesn't overlap, we add it.
|
|
93
|
+
const acceptedMatches = [];
|
|
94
|
+
// 為了效能,我們實作一個簡單的區間檢查
|
|
95
|
+
// 由於我們可能有大量的匹配,線性掃描 acceptedMatches (O(M)) 對每個候選 (N) -> O(NM)。
|
|
96
|
+
// 如果 M 很大,這會慢。
|
|
97
|
+
// 優化:使用一個簡單的遮罩或區間樹?
|
|
98
|
+
// 考量到 JS 的 overhead,對於一般長度的文本,線性掃描可能已經足夠快。
|
|
99
|
+
// 但 Reviewer 提到效能,我們來做一個稍微好一點的檢查。
|
|
100
|
+
// 我們可以使用一個 Uint8Array 來標記被佔用的位置,如果文本長度允許 (e.g. < 1MB)。
|
|
101
|
+
// 這是 O(1) 檢查,O(L) 標記。
|
|
102
|
+
// 如果文本太長,回退到區間檢查。
|
|
103
|
+
// 假設大部分檢查的文本都在 100KB 以內。
|
|
104
|
+
if (text.length < 100000) {
|
|
105
|
+
const occupied = new Uint8Array(text.length);
|
|
106
|
+
for (const candidate of allMatches) {
|
|
107
|
+
let isOverlapping = false;
|
|
108
|
+
// Check overlap
|
|
109
|
+
for (let i = candidate.start; i < candidate.end; i++) {
|
|
110
|
+
if (occupied[i] === 1) {
|
|
111
|
+
isOverlapping = true;
|
|
112
|
+
break;
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
if (!isOverlapping) {
|
|
116
|
+
acceptedMatches.push(candidate);
|
|
117
|
+
// Mark occupied
|
|
118
|
+
for (let i = candidate.start; i < candidate.end; i++) {
|
|
119
|
+
occupied[i] = 1;
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
else {
|
|
125
|
+
// Fallback for very long text: Interval List
|
|
126
|
+
// Keep intervals sorted by start
|
|
127
|
+
const acceptedIntervals = [];
|
|
128
|
+
for (const candidate of allMatches) {
|
|
129
|
+
// Binary search or linear scan? Linear scan is O(M).
|
|
130
|
+
// Check overlap with any accepted interval
|
|
131
|
+
const isOverlapping = acceptedIntervals.some(interval => candidate.start < interval.end && candidate.end > interval.start);
|
|
132
|
+
if (!isOverlapping) {
|
|
133
|
+
acceptedMatches.push(candidate);
|
|
134
|
+
acceptedIntervals.push({ start: candidate.start, end: candidate.end });
|
|
135
|
+
// No need to sort acceptedIntervals every time if we just use .some()
|
|
136
|
+
// But for binary search we would need to maintain order.
|
|
137
|
+
// Given the typical number of matches, .some() is acceptable here compared to strict O(N^2) if M is small.
|
|
138
|
+
// Wait, previous logic WAS O(N*M) where M is accepted count. This is same.
|
|
139
|
+
// But Uint8Array is O(N * Len).
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
// 3. 最終排序:按位置輸出,符合閱讀順序
|
|
144
|
+
return acceptedMatches.sort((a, b) => a.start - b.start);
|
|
79
145
|
}
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
const newMatch = {
|
|
146
|
+
addMatch(allMatches, match, entry, dictName, isVariant = false) {
|
|
147
|
+
allMatches.push({
|
|
83
148
|
...match,
|
|
84
149
|
replacement: entry.taiwan,
|
|
85
150
|
confidence: entry.confidence,
|
|
86
151
|
rule: `${dictName}-${entry.match_type || 'exact'}${isVariant ? '-variant' : ''}`,
|
|
87
152
|
autofix_safe: entry.autofix_safe || false
|
|
88
|
-
};
|
|
89
|
-
// 如果這個範圍還沒有匹配,或者新匹配的信心度更高
|
|
90
|
-
const existingMatch = processedRanges.get(rangeKey);
|
|
91
|
-
if (!existingMatch || newMatch.confidence > existingMatch.confidence) {
|
|
92
|
-
if (existingMatch) {
|
|
93
|
-
// 移除舊的匹配
|
|
94
|
-
const index = allMatches.indexOf(existingMatch);
|
|
95
|
-
if (index > -1) {
|
|
96
|
-
allMatches.splice(index, 1);
|
|
97
|
-
}
|
|
98
|
-
}
|
|
99
|
-
processedRanges.set(rangeKey, newMatch);
|
|
100
|
-
allMatches.push(newMatch);
|
|
101
|
-
}
|
|
153
|
+
});
|
|
102
154
|
}
|
|
103
155
|
async scanAvailableDictionaries() {
|
|
104
156
|
try {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"dictionary-manager.js","sourceRoot":"","sources":["../../src/core/dictionary-manager.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAA;AACtC,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,MAAM,CAAA;AACpC,OAAO,EAAE,aAAa,EAAE,MAAM,KAAK,CAAA;AAEnC,OAAO,EAAE,WAAW,EAAE,MAAM,yBAAyB,CAAA;AACrD,OAAO,EAAE,qBAAqB,EAAE,MAAM,gCAAgC,CAAA;AACtE,OAAO,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAA;AAEzC,MAAM,OAAO,iBAAiB;IACpB,KAAK,GAAG,IAAI,QAAQ,CAAuB,EAAE,CAAC,CAAA,CAAC,cAAc;IACpD,gBAAgB,CAAQ;IACxB,gBAAgB,CAAuB;IAExD,YAAY,gBAAyB,EAAE,YAAqB;QAC1D,gBAAgB;QAChB,IAAI,CAAC,KAAK,GAAG,IAAI,QAAQ,CAAuB,YAAY,IAAI,EAAE,CAAC,CAAA;QAEnE,IAAI,gBAAgB,EAAE,CAAC;YACrB,IAAI,CAAC,gBAAgB,GAAG,gBAAgB,CAAA;QAC1C,CAAC;aAAM,CAAC;YACN,2BAA2B;YAC3B,MAAM,UAAU,GAAG,OAAO,CAAC,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAA;YAC1D,IAAI,CAAC,gBAAgB,GAAG,IAAI,CAAC,UAAU,EAAE,IAAI,EAAE,cAAc,CAAC,CAAA;QAChE,CAAC;QACD,IAAI,CAAC,gBAAgB,GAAG,IAAI,qBAAqB,EAAE,CAAA;IACrD,CAAC;IAED,KAAK,CAAC,cAAc,CAAC,IAAY;QAC/B,IAAI,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC;YACzB,OAAO,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,IAAI,CAAE,CAAA;QAC9B,CAAC;QAED,IAAI,CAAC;YACH,MAAM,QAAQ,GAAG,IAAI,CAAC,IAAI,CAAC,gBAAgB,EAAE,GAAG,IAAI,OAAO,CAAC,CAAA;YAC5D,MAAM,OAAO,GAAG,MAAM,QAAQ,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAA;YACjD,MAAM,IAAI,GAAiB,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,CAAA;YAE9C,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,IAAI,EAAE,IAAI,CAAC,CAAA;YAC1B,OAAO,IAAI,CAAA;QACb,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,MAAM,IAAI,KAAK,CAAC,8BAA8B,IAAI,MAAM,WAAW,CAAC,KAAK,CAAC,EAAE,CAAC,CAAA;QAC/E,CAAC;IACH,CAAC;IAED,WAAW,CAAC,IAAY;QACtB,MAAM,UAAU,GAAkB,EAAE,CAAA;
|
|
1
|
+
{"version":3,"file":"dictionary-manager.js","sourceRoot":"","sources":["../../src/core/dictionary-manager.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* IgnoreFileLoader - 載入 .twlintignore 檔案
|
|
3
|
+
*
|
|
4
|
+
* 類似 ESLint 的 .eslintignore 功能
|
|
5
|
+
*/
|
|
6
|
+
export declare class IgnoreFileLoader {
|
|
7
|
+
/**
|
|
8
|
+
* 嘗試載入 .twlintignore 檔案
|
|
9
|
+
*
|
|
10
|
+
* @param cwd 當前工作目錄
|
|
11
|
+
* @returns ignore patterns 陣列,找不到檔案時回傳空陣列
|
|
12
|
+
*/
|
|
13
|
+
static load(cwd?: string): Promise<string[]>;
|
|
14
|
+
/**
|
|
15
|
+
* 解析 .twlintignore 檔案內容
|
|
16
|
+
*
|
|
17
|
+
* 格式規則:
|
|
18
|
+
* - 每行一個 glob pattern
|
|
19
|
+
* - # 開頭為註解
|
|
20
|
+
* - 空行會被忽略
|
|
21
|
+
* - 目錄結尾 / 會自動轉換為 /**
|
|
22
|
+
*/
|
|
23
|
+
private static parseIgnoreFile;
|
|
24
|
+
/**
|
|
25
|
+
* 檢查 .twlintignore 檔案是否存在
|
|
26
|
+
*/
|
|
27
|
+
static exists(cwd?: string): Promise<boolean>;
|
|
28
|
+
}
|
|
29
|
+
//# sourceMappingURL=ignore-file-loader.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ignore-file-loader.d.ts","sourceRoot":"","sources":["../../src/core/ignore-file-loader.ts"],"names":[],"mappings":"AAGA;;;;GAIG;AACH,qBAAa,gBAAgB;IAC3B;;;;;OAKG;WACU,IAAI,CAAC,GAAG,GAAE,MAAsB,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC;IAajE;;;;;;;;OAQG;IACH,OAAO,CAAC,MAAM,CAAC,eAAe;IAyB9B;;OAEG;WACU,MAAM,CAAC,GAAG,GAAE,MAAsB,GAAG,OAAO,CAAC,OAAO,CAAC;CASnE"}
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
import { readFile, access } from 'fs/promises';
|
|
2
|
+
import { resolve } from 'path';
|
|
3
|
+
/**
|
|
4
|
+
* IgnoreFileLoader - 載入 .twlintignore 檔案
|
|
5
|
+
*
|
|
6
|
+
* 類似 ESLint 的 .eslintignore 功能
|
|
7
|
+
*/
|
|
8
|
+
export class IgnoreFileLoader {
|
|
9
|
+
/**
|
|
10
|
+
* 嘗試載入 .twlintignore 檔案
|
|
11
|
+
*
|
|
12
|
+
* @param cwd 當前工作目錄
|
|
13
|
+
* @returns ignore patterns 陣列,找不到檔案時回傳空陣列
|
|
14
|
+
*/
|
|
15
|
+
static async load(cwd = process.cwd()) {
|
|
16
|
+
const ignoreFilePath = resolve(cwd, '.twlintignore');
|
|
17
|
+
try {
|
|
18
|
+
await access(ignoreFilePath);
|
|
19
|
+
const content = await readFile(ignoreFilePath, 'utf-8');
|
|
20
|
+
return this.parseIgnoreFile(content);
|
|
21
|
+
}
|
|
22
|
+
catch {
|
|
23
|
+
// 找不到 .twlintignore 檔案,回傳空陣列
|
|
24
|
+
return [];
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* 解析 .twlintignore 檔案內容
|
|
29
|
+
*
|
|
30
|
+
* 格式規則:
|
|
31
|
+
* - 每行一個 glob pattern
|
|
32
|
+
* - # 開頭為註解
|
|
33
|
+
* - 空行會被忽略
|
|
34
|
+
* - 目錄結尾 / 會自動轉換為 /**
|
|
35
|
+
*/
|
|
36
|
+
static parseIgnoreFile(content) {
|
|
37
|
+
return content
|
|
38
|
+
.split('\n')
|
|
39
|
+
.map(line => line.trim())
|
|
40
|
+
.filter(line => {
|
|
41
|
+
// 過濾空行和註解
|
|
42
|
+
if (!line)
|
|
43
|
+
return false;
|
|
44
|
+
if (line.startsWith('#'))
|
|
45
|
+
return false;
|
|
46
|
+
return true;
|
|
47
|
+
})
|
|
48
|
+
.map(line => {
|
|
49
|
+
// 處理目錄模式(結尾 /)
|
|
50
|
+
if (line.endsWith('/')) {
|
|
51
|
+
return line + '**';
|
|
52
|
+
}
|
|
53
|
+
// 如果模式不包含 / 和 *,加上 **/ 前綴以匹配任何深度
|
|
54
|
+
if (!line.includes('/') && !line.includes('*')) {
|
|
55
|
+
return '**/' + line;
|
|
56
|
+
}
|
|
57
|
+
return line;
|
|
58
|
+
});
|
|
59
|
+
}
|
|
60
|
+
/**
|
|
61
|
+
* 檢查 .twlintignore 檔案是否存在
|
|
62
|
+
*/
|
|
63
|
+
static async exists(cwd = process.cwd()) {
|
|
64
|
+
const ignoreFilePath = resolve(cwd, '.twlintignore');
|
|
65
|
+
try {
|
|
66
|
+
await access(ignoreFilePath);
|
|
67
|
+
return true;
|
|
68
|
+
}
|
|
69
|
+
catch {
|
|
70
|
+
return false;
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
//# sourceMappingURL=ignore-file-loader.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ignore-file-loader.js","sourceRoot":"","sources":["../../src/core/ignore-file-loader.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,EAAE,MAAM,aAAa,CAAA;AAC9C,OAAO,EAAE,OAAO,EAAE,MAAM,MAAM,CAAA;AAE9B;;;;GAIG;AACH,MAAM,OAAO,gBAAgB;IAC3B;;;;;OAKG;IACH,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,MAAc,OAAO,CAAC,GAAG,EAAE;QAC3C,MAAM,cAAc,GAAG,OAAO,CAAC,GAAG,EAAE,eAAe,CAAC,CAAA;QAEpD,IAAI,CAAC;YACH,MAAM,MAAM,CAAC,cAAc,CAAC,CAAA;YAC5B,MAAM,OAAO,GAAG,MAAM,QAAQ,CAAC,cAAc,EAAE,OAAO,CAAC,CAAA;YACvD,OAAO,IAAI,CAAC,eAAe,CAAC,OAAO,CAAC,CAAA;QACtC,CAAC;QAAC,MAAM,CAAC;YACP,6BAA6B;YAC7B,OAAO,EAAE,CAAA;QACX,CAAC;IACH,CAAC;IAED;;;;;;;;OAQG;IACK,MAAM,CAAC,eAAe,CAAC,OAAe;QAC5C,OAAO,OAAO;aACX,KAAK,CAAC,IAAI,CAAC;aACX,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC;aACxB,MAAM,CAAC,IAAI,CAAC,EAAE;YACb,UAAU;YACV,IAAI,CAAC,IAAI;gBAAE,OAAO,KAAK,CAAA;YACvB,IAAI,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC;gBAAE,OAAO,KAAK,CAAA;YACtC,OAAO,IAAI,CAAA;QACb,CAAC,CAAC;aACD,GAAG,CAAC,IAAI,CAAC,EAAE;YACV,eAAe;YACf,IAAI,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,EAAE,CAAC;gBACvB,OAAO,IAAI,GAAG,IAAI,CAAA;YACpB,CAAC;YAED,iCAAiC;YACjC,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,EAAE,CAAC;gBAC/C,OAAO,KAAK,GAAG,IAAI,CAAA;YACrB,CAAC;YAED,OAAO,IAAI,CAAA;QACb,CAAC,CAAC,CAAA;IACN,CAAC;IAED;;OAEG;IACH,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,MAAc,OAAO,CAAC,GAAG,EAAE;QAC7C,MAAM,cAAc,GAAG,OAAO,CAAC,GAAG,EAAE,eAAe,CAAC,CAAA;QACpD,IAAI,CAAC;YACH,MAAM,MAAM,CAAC,cAAc,CAAC,CAAA;YAC5B,OAAO,IAAI,CAAA;QACb,CAAC;QAAC,MAAM,CAAC;YACP,OAAO,KAAK,CAAA;QACd,CAAC;IACH,CAAC;CACF"}
|
package/dist/core/linter.d.ts
CHANGED
|
@@ -1,19 +1,56 @@
|
|
|
1
|
-
import type { LintResult, Issue,
|
|
1
|
+
import type { LintResult, Issue, TWLintUserConfig } from '../types.js';
|
|
2
2
|
export declare class TWLinter {
|
|
3
3
|
private dictManager;
|
|
4
4
|
private rules;
|
|
5
5
|
private config;
|
|
6
6
|
private deepMode;
|
|
7
|
-
|
|
7
|
+
private configMatcher;
|
|
8
|
+
private twlintignoreLoaded;
|
|
9
|
+
constructor(config: TWLintUserConfig, options?: {
|
|
8
10
|
deep?: boolean;
|
|
9
11
|
});
|
|
12
|
+
/**
|
|
13
|
+
* 載入 .twlintignore 檔案(如果存在)
|
|
14
|
+
*
|
|
15
|
+
* 這個方法會在第一次需要時自動呼叫
|
|
16
|
+
*/
|
|
17
|
+
private loadTwlintignore;
|
|
10
18
|
private initializeRules;
|
|
11
19
|
lintFiles(patterns: string[]): Promise<LintResult[]>;
|
|
12
|
-
lintText(text: string,
|
|
13
|
-
fixText(text: string): Promise<string>;
|
|
20
|
+
lintText(text: string, filePath?: string): Promise<Issue[]>;
|
|
21
|
+
fixText(text: string, filePath?: string): Promise<string>;
|
|
14
22
|
private expandFilePatterns;
|
|
15
|
-
|
|
23
|
+
/**
|
|
24
|
+
* 取得基礎忽略模式(僅用於 glob 擴展時的初步過濾)
|
|
25
|
+
*
|
|
26
|
+
* 注意:
|
|
27
|
+
* - 系統鐵律(SYSTEM_IGNORES)已在 ConfigMatcher 處理
|
|
28
|
+
* - 這裡只需要最基本的過濾,避免 glob 擴展時掃描過多檔案
|
|
29
|
+
*/
|
|
30
|
+
private getBaseIgnorePatterns;
|
|
31
|
+
/**
|
|
32
|
+
* 根據檔案路徑載入對應的詞庫
|
|
33
|
+
*/
|
|
34
|
+
private loadDictionariesForFile;
|
|
35
|
+
/**
|
|
36
|
+
* 取得預設詞庫列表
|
|
37
|
+
*/
|
|
38
|
+
private getDefaultDictionaries;
|
|
39
|
+
/**
|
|
40
|
+
* 舊方法保留向後相容
|
|
41
|
+
*/
|
|
16
42
|
private loadDictionaries;
|
|
43
|
+
/**
|
|
44
|
+
* 根據檔案路徑獲取適用的規則
|
|
45
|
+
*/
|
|
46
|
+
private getActiveRulesForFile;
|
|
47
|
+
/**
|
|
48
|
+
* 取得預設規則
|
|
49
|
+
*/
|
|
50
|
+
private getDefaultRules;
|
|
51
|
+
/**
|
|
52
|
+
* 舊方法保留向後相容
|
|
53
|
+
*/
|
|
17
54
|
private getActiveRules;
|
|
18
55
|
/**
|
|
19
56
|
* 檢查規則是否啟用
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"linter.d.ts","sourceRoot":"","sources":["../../src/core/linter.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"linter.d.ts","sourceRoot":"","sources":["../../src/core/linter.ts"],"names":[],"mappings":"AAQA,OAAO,KAAK,EAAE,UAAU,EAAE,KAAK,EAAE,gBAAgB,EAAQ,MAAM,aAAa,CAAA;AAI5E,qBAAa,QAAQ;IACnB,OAAO,CAAC,WAAW,CAAmB;IACtC,OAAO,CAAC,KAAK,CAA0B;IACvC,OAAO,CAAC,MAAM,CAAkB;IAChC,OAAO,CAAC,QAAQ,CAAQ;IACxB,OAAO,CAAC,aAAa,CAAe;IACpC,OAAO,CAAC,kBAAkB,CAAQ;gBAEtB,MAAM,EAAE,gBAAgB,EAAE,OAAO,CAAC,EAAE;QAAE,IAAI,CAAC,EAAE,OAAO,CAAA;KAAE;IAQlE;;;;OAIG;YACW,gBAAgB;IAW9B,OAAO,CAAC,eAAe;IAQjB,SAAS,CAAC,QAAQ,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,UAAU,EAAE,CAAC;IAiCpD,QAAQ,CAAC,IAAI,EAAE,MAAM,EAAE,QAAQ,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,KAAK,EAAE,CAAC;IA+B3D,OAAO,CAAC,IAAI,EAAE,MAAM,EAAE,QAAQ,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;YAkBjD,kBAAkB;IA4BhC;;;;;;OAMG;YACW,qBAAqB;IAkCnC;;OAEG;YACW,uBAAuB;IAsCrC;;OAEG;IACH,OAAO,CAAC,sBAAsB;IAK9B;;OAEG;YACW,gBAAgB;IAgB9B;;OAEG;IACH,OAAO,CAAC,qBAAqB;IAoB7B;;OAEG;IACH,OAAO,CAAC,eAAe;IAQvB;;OAEG;IACH,OAAO,CAAC,cAAc;IAKtB;;OAEG;IACH,OAAO,CAAC,YAAY;IAMpB;;OAEG;IACH,OAAO,CAAC,yBAAyB;CAUlC"}
|