Skip to content

Commit a4a5544

Browse files
committed
fixname: unicode and messy check opt
1 parent ce5cb5b commit a4a5544

File tree

11 files changed

+94
-68
lines changed

11 files changed

+94
-68
lines changed

cmd/cmd_fixname.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -213,6 +213,8 @@ async function fixFileName(f) {
213213
// 执行繁体转简体操作
214214
oldBase = sify(oldBase)
215215
}
216+
// 确保文件名不含有文件系统不允许的非法字符
217+
oldBase = helper.filenameSafe(oldBase);
216218
// 生成修复后的新路径,包括旧基础路径和文件扩展名
217219
const newName = `${oldBase}${ext}`
218220
const newPath = path.join(newDir, newName);

cmd/cmd_prefix.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -317,6 +317,8 @@ async function createNewNameByMode(f) {
317317
log.info(logTag, `IgnorePrefix: ${ipx} ${helper.pathShort(f.path)}`);
318318
prefix = "";
319319
}
320+
// 确保文件名不含有文件系统不允许的非法字符
321+
oldBase = helper.filenameSafe(oldBase);
320322
let fullBase = prefix.length > 0 ? (prefix + sep + oldBase) : oldBase;
321323
// 去除首位空白和特殊字符
322324
fullBase = fullBase.replaceAll(reStripUglyChars, "");

cmd/cmd_shared.js

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,16 +29,17 @@ async function renameOneFile(f) {
2929
log.showYellow("Rename", "ignore", f.path);
3030
return;
3131
}
32-
log.showGray(`Source: ${f.path}`);
3332
try {
3433
// 确保输出目录已存在,如果不存在则创建
3534
const outDir = path.dirname(outPath);
3635
if (!await fs.pathExists(outDir)) {
3736
await fs.mkdirs(outDir);
3837
}
38+
3939
// 使用 fs 模块的 rename 方法重命名文件,并等待操作完成
4040
await fs.rename(f.path, outPath);
4141
// 打印重命名成功的日志信息,显示输出文件的路径
42+
log.showGray(`Source: ${f.path}`);
4243
log.show(`${chalk.green(`Renamed:`)} ${outPath}`);
4344
log.fileLog(`Done: <${f.path}> => ${f.outName}`, "Rename");
4445
return f;

lib/encoding.js

Lines changed: 40 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ import iconv from 'iconv-lite';
44
import os from 'os';
55
import path from 'path';
66
import * as log from './debug.js';
7-
import { strHasASCII, strHasHFKanaHira, strHasHiraKana, strOnlyASCII, strOnlyChinese, strOnlyJapanese } from './unicode.js';
7+
import { strHasASCII, strHasHFKanaHira, strHasHiraKana, strOnlyASCII, strOnlyChinese, strOnlyJapanese, strOnlyJapaneseHan } from './unicode.js';
88
import { CHINESE_CHARS_3500, MESSY_CJK_CHARS as MESSY_CJK_CHARS_ } from './unicode_data.js';
99

1010
// https://github.com/bnoordhuis/node-iconv/
@@ -32,7 +32,7 @@ export const MESSY_CJK_CHARS = MESSY_CJK_CHARS_
3232

3333
export const REGEX_MESSY_CJK = new RegExp(`[${MESSY_CJK_CHARS}]`, 'u')
3434

35-
export const REGEX_MESSY_CJK_EXT = /[\u8701-\u883f\u9200-\u9484]/u //生僻字: 虫字旁 金字旁
35+
export const REGEX_MESSY_CJK_EXT = /[\u8720-\u883f\u9300-\u9484]/u //生僻字: 虫字旁 金字旁
3636

3737
export const REGEX_MESSY_UNICODE = /[\u007f-\u00a0\u00c0-\u017f\u0400-\u1cff\u2070-\u24ff\u0e00-\u0e7f\u3400-\u4dbf\uac00-\uf8ff\ufe30-\ufe4f\ufff0-\uffff]/u
3838

@@ -52,25 +52,34 @@ export function checkBadUnicode(str) {
5252
// 乱码标志 问号和黑问号
5353
results.push([true, 0, `非法字符`])
5454
}
55-
if (/[\u00c0-\u00d6\u00d8-\u024f\u3100-\u312f\ua720-\ua7ff\uab30-\uabff]/u.test(str)) {
55+
if (/[\u00c0-\u00d6\u00d8-\u024f\u3100-\u312f]/u.test(str)) {
5656
// 乱码标志 拉丁字母扩展 注音符号
5757
results.push([true, 2, `拉丁字母扩展`])
5858
}
59-
if (/[\u0530-\u1cff]/u.test(str)) {
60-
// 乱码标志 小众语言字母符号
61-
results.push([true, 3, `小众语言符号`])
59+
if (/[\u3300-\u33ff]/u.test(str)) {
60+
// 乱码标志 特殊字符
61+
results.push([true, 4, `CJK特殊字符`])
6262
}
63-
if (/[\u3300-\u3357]/u.test(str)) {
64-
// 乱码标志 方块片假名
65-
results.push([true, 4, `方块片假名`])
63+
if (/[\u0370-\u1cff]/u.test(str)) {
64+
// 乱码标志 小众语言符号
65+
results.push([true, 3, `小众语言A`])
66+
}
67+
if (/[\ua000-\ua7ff\uab30-\uabff\ud7b0-\ud7ff]/u.test(str)) {
68+
// 乱码标志 小众语言符号
69+
results.push([true, 4, `小众语言B`])
70+
}
71+
if (/[\ud800-\udfff]/u.test(str)) {
72+
// 乱码标志 代理对,存疑
73+
results.push([true, 4, `代理对`])
6674
}
6775
if (/[\ue000-\uf8ff]/u.test(str)) {
6876
// 乱码标志 Unicode私有区
6977
results.push([true, 5, `私有区`])
7078
}
7179
if (/[\uff66-\uff9d]/u.test(str)) {
80+
// 暂时忽略,还比较常用
7281
// 乱码标志 半角平假名片假名
73-
results.push([true, 6, `半角假名`])
82+
// results.push([true, 6, `半角假名`])
7483
}
7584
if (/[㼿]/u.test(str)) {
7685
// 乱码标志 特殊生僻字
@@ -113,6 +122,8 @@ export function fixCJKEncImpl(str,
113122
// results.push([str, false, 0])
114123
return [[str, false, 0, '全英文数字', ''],]
115124
}
125+
log.info('---------------------')
126+
log.info('fixCJKEnc', str)
116127
if (!REGEX_MESSY_UNICODE.test(str)
117128
&& !REGEX_MESSY_CJK.test(str)
118129
&& !REGEX_MESSY_CJK_EXT.test(str)) {
@@ -152,14 +163,15 @@ export function fixCJKEncImpl(str,
152163
let strDecoded = iconv.decode(strBuffer, enc2)
153164
const badDecoded = checkBadUnicode(strDecoded)
154165
// const strCleaned = strDecoded.replaceAll(/[\ufffd\u0020]/ugi, '')
166+
log.info(enc1, enc2, strDecoded, badDecoded)
155167
// 如果含有乱码字符
156168
if (badDecoded?.length > 0) {
157169
for (const item of badDecoded) {
158170
results.push([strDecoded, ...item, `${enc1}=>${enc2}`])
159171
}
172+
160173
continue;
161174
}
162-
163175
// log.showRed('========')
164176
// log.showRed(str)
165177
// log.showGreen(Array.from(str).map(c => c.codePointAt(0).toString(16)))
@@ -168,8 +180,16 @@ export function fixCJKEncImpl(str,
168180
const onlyASCII = strOnlyASCII(strDecoded)
169181
const onlyCN = strOnlyChinese(strDecoded)
170182
const onlyJP = strOnlyJapanese(strDecoded)
183+
const onlyJPHan = strOnlyJapaneseHan(strDecoded)
184+
const hasHiraKana = strHasHiraKana(strDecoded)
185+
const hasHFHiraKana = strHasHFKanaHira(strDecoded)
171186
const messyUnicode = REGEX_MESSY_UNICODE.test(strDecoded)
172187
const messyCJK = REGEX_MESSY_CJK.test(strDecoded)
188+
const messyCJKExt = REGEX_MESSY_CJK_EXT.test(strDecoded)
189+
190+
log.debug(strDecoded, onlyASCII, onlyCN, onlyJP, onlyJPHan, messyCJK)
191+
log.debug(strDecoded, hasHiraKana, hasHFHiraKana, messyUnicode, messyCJK)
192+
173193
if (onlyASCII && !strDecoded.includes('?')) {
174194
results.push([strDecoded, true, 99, `全英文数字`, `${enc1}=>${enc2}`])
175195
break
@@ -178,25 +198,21 @@ export function fixCJKEncImpl(str,
178198
results.push([strDecoded, true, 99, `常用汉字`, `${enc1}=>${enc2}`])
179199
break
180200
}
181-
log.debug(strDecoded, onlyCN, onlyJP, messyUnicode, messyCJK)
201+
if (messyCJK || messyCJKExt) {
202+
results.push([strDecoded, true, 50, `CJK罕见`, `${enc1}=>${enc2}`])
182203

183-
if (onlyJP && strHasHiraKana(strDecoded)) {
184-
results.push([strDecoded, true, 78, `日文字符`, `${enc1}=>${enc2}`])
204+
}
205+
if (onlyJP) {
206+
if (strHasHiraKana(strDecoded) || onlyJPHan) {
207+
results.push([strDecoded, true, 78, `日文字符`, `${enc1}=>${enc2}`])
208+
}
185209
}
186210
else if (onlyCN) {
187211
results.push([strDecoded, true, 76, `中文字符`, `${enc1}=>${enc2}`])
188212
}
189-
else if (!messyUnicode && !messyCJK
190-
&& [enc1, enc2].includes('SHIFT_JIS')
191-
&& [enc1, enc2].includes('UTF8')) {
192-
results.push([strDecoded, true, 74, `无特殊字符`, `${enc1}=>${enc2}`])
213+
else if (strHasHFKanaHira || strHasHiraKana) {
214+
results.push([strDecoded, true, 65, `含日文假名`, ` ${enc1}=>${enc2}`])
193215
}
194-
// else if (messyCJK) {
195-
// results.push([strDecoded, true, 51, `含特殊汉字`, `${enc1}=>${enc2}`])
196-
// }
197-
// else if (messyUnicode) {
198-
// results.push([strDecoded, true, 52, `含特殊符号`, `${enc1}=>${enc2}`])
199-
// }
200216
else {
201217
results.push([strDecoded, true, 60, `正常转换 ${onlyCN} ${onlyJP}`, ` ${enc1}=>${enc2}`])
202218
}

lib/helper.js

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -203,6 +203,11 @@ export function pathExt(filename, toLowerCase = false) {
203203
return toLowerCase ? ext?.toLowerCase() : ext;
204204
}
205205

206+
const REGEX_ILLEGAL_FILENAME = /[\x00-\x1F\x7F<>:"\/\\|?*]/gm
207+
export function filenameSafe(name) {
208+
return name.replaceAll(REGEX_ILLEGAL_FILENAME, '')
209+
}
210+
206211
export function getSafeDeletedDir(filepath) {
207212
const dtStr = dayjs().format("YYYYMMDD");
208213
const dir = path.join(pathRoot(filepath), 'Deleted_By_Mediac', dtStr);

lib/messy_hanzi.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
娾僾壒鑀葊蓭儑垵貋嶅摮謷謸慠巼弝垻跁贁斒螌褩闆螁捠邫艕闁怉堢賲藵菢袌虣儤揹藣郥偝偹僃蛽翉楍倴桳撪輽埲偪楅螕聛貏邲苾袐弻煏蓽蜌廦覍徧艑脿幖儦藨謤贆諘虌彆邠儐虨臏抦昞棅偋傡剝袚缽僠瓟葧艊攃婇傪朁摻儏謲傖賶嶆蓸敇蓛箣憡偛艖詧祡袃訍蠆幨攙僝儃剷嵼幝閳譂讇锠僘謿巐仦蛼諃迧茞軙樄曟趻贂棦偁僜罉脭庱彨彲翄懘趩翀憃蹖揰搊菗椆摴貙幮藸傗滀蓫儊諔臅暷輲僢菙堾輴滣偆賰娕偨蠀嬨皉茦莿螆茐棇蓯聦婃欉謥脨趗憱顣鑹櫕缞嶉磪脺膬臎乼竴虘蟽軑軚艜蹛聸僤蓞贉簹艡欓讜儅趤壔翢艔軇瓙脦艠櫈袛藡拞菧聜偙僀嶳傎嵮蹎奌婰蜔訋蓧恎昳绖戜惵褋艓帄倲埬菄徚蕫迵戙枓脰嬻讟螙偳褍塅嵟逇敪埵軃尮偔崿詻僫讍奀峏栭厼趰誀茷傠蕟忛勫柉羳鐢蠜奿訉軓婏蕜杮鐨翂訜岎幩蕡羵僨膹偑僼鎽霻摓艂覂賵覅缹缻邞紨岪翇虙葍粰呒蜅撨峊袝偩覄褔蕧祴忋槩忓尷仠堈掆罁焹戅菒藳犵鎶輵挭拲羾莻袧褠茩苽箛唃傦脵崓僱詿柺覌輨泴悺罆茪僙椝槼螝膭蛫嶡蓘輥謴濄彍聝惈螒譀迒貥茠椃諕蠔悎傐抲蠚峆楁詥貈螛礉垎袔熇詪悙脝噷叿渹輷鍧纮垬娂翃粠葒綋翝晎闂闀葔虖軤膴謼螜虝嫮熩鍙婲搳撶螖諙諣褢褱貛寏藧巟偟葟熿艎趪詤愰婎幑褘撝蜖詯僡藱儶孈梡佸旤艧僟銈賷鐖覉忣揤偮庴塉檝螏鍓艥妀茍茤紒惎葪諅乫貑鎵忦蛺幏惤葌椷椾蕳熸瀐鐧虃弿謭蠒鐗葥諓翞螀傋弶謽茮虠嶕膲儌憿敿訆漖趭菨堦脻謯迼偼媫楬蜐蓵蠞蠘悈蛶褯兓惍巹蓳僸濅賮葏聙蟼曔僒褧奺欍崌跔艍諊僪蹫聥乬邭袓埾虡寠勮懅貗脧鎸埍菤臇覐趹傕蕝臄觼貜覠鍕晙懏擖欬偘埳惂邟囥犺鈧趷揢翗愙艐摼埪涳郀跍趶廤褲姱儈旝邼狅軖軠岲聧楏虁蹞聭蕢樻聵熴閫閸睏翋搚藞攋蠟婡崍賴葻懢攔讕襽郞艆蜋鎯蓢樃崀僗鐒蔂儽壨虆欙傫藟蠝鑸銇攂倰菞棃艃褵謧邌孋邐涖脷厤棙蛠蝷曆儮曞蠇壢藶觻欐讈梿覝聫褳聮螊謰蹥羷僆墚輬脼嶛膫屪廫賿蹘藔尦尞茢迾脟巤儠冧晽粦亃癛旈藰嬼翏廇蕯壠慺艛謱塿蓾艣鐪菉趢蹗鯥虂藘捛屢儢曫虊惀菕錀埨覙鏍儸攞欏曪洜嬤螞杩傌屘鏋槾澷庬莾茻貓軞乮蓩覒愗嚜脢槑徾嵄媺跊菛虋夣詸擟攠葞覔覛榓偭覕搣懱僶慜蠠姳慏詺謩擵懡眿蛨暯銆藦鏌怽畞莯幙艒鎿袦軜摨嬭褦螚暔擃儾怓巎抐脮埿聣抳儗儞聻伲迡堄嫟愵跈蹍蹨艌褭揑惗菍巕讘钀脌甯儜蕽挊羺鐞傉搙蹃藲鏂掱輫渒溿嗙褜奅斾蓜嶏葐梈旇翍壀脴擗鷿楄覑僄蠙聠呯帲幈缾蓱蛢輧敀娝擈菐贌巭迉桼蛣僛諆亝旂帺掑軝愭懠艩蠐邔婍忔湇罊蟿缼婜孯諐偂軡脥嗛傔儙輤蹡廧羻趬菬癄藮趫帩僺聺蛪鍥嶔菦嫀慬懄蠄笉梫菣撳埥夝剠殑葝檾掅儬宆儝藭丠媝蓲趥訅蛷菃翑葋鑺蝺迲奍峑婘葲烇虇崅夋衻袇袡媣儴讱屻岃訒軔梕茙峵媶搑褣螎嬫巆傇輮鍒蕠曘嗕偄輭膶虄僿褬濏譅桬儍翜翣邖挻脠軕搧羴晱訕傓僐敾樿蟺謪绱蕱袑蛥蠂屾葠訷蓡詵邥谉渖諗曋脤蜄瘮苼曻鉎鍟偗渻賸邿褷鍦乭姼枾媞煶諟鏉杸掓軗虪慡脽虒恖蕬螄柶蕼愯廀摉叜傁擻梀傃藗葰嵗鐩蕵傞摍溑褨鏁褟枱炲菭儓嬯忲惔墰墵燂罈藫貚傝僋蹚傏漟偒幍轁貣膯幐邆虅偍蕛趧蹏鍗悐揥趯屇庣蓨宨嬥覜聼邒閮聤娗脡蓪峝晍詷膧媮妵庩悇捈梌鍎迌貒剸鏄褖蓷藬尵蹪俀僓蹆軘臋讬袥脫沲迱袉跅媧嗗邷夞帵貦埦脕贃暀蛧迋葨詴嶶蓶鍏闈愇撱諉儰苿叞菋媦藯讏塭輼轀螡閺脗妏顐璺螉聬攚罋涹偓楃擭臒弙箼螐祦儛屼忢悞嵍邜傒翖嶲橀熻螇貕觽觿椺謵鎴蹝呬忥恄蕮虩傄翈敮蕸僲憸蹮妶蛝輱藖獮鍌幰攇峴晛缐僩僴壏膷鑲蠁缿宯虓翛膮虈郩涍詨斅峫翓讗藛缷偞偰僁褉嶰邤杺軐脪蛵曐侀讻詾賯诇脙鏅潃褎褏螑晇訏虗谞虛蕦諝譃呴偦詡怴欰藚吅弲梋鋗蕿蠉蜁嫙檈晅袨眴鏇袕壆瀥焄壎臐壦攳迿訙吖笌漄蕥偣綖詽虤壛巗椼褗覎葕傿椻暥嬊觾讞輰鍚岟炴傟懩傜摿暚邎宎抭偠袎覞艞讑僷曅歋擛悘毉侇迻宧巸弬栘袘訑貤蛦箷彛螔謻讉庡逘偯敼螘帠袣埶幆晹蛡跇嫕蓺槸艗貖賹藙贀虉讛訔訚崯朄讔憗懚粌偀愥绬嫈罃褮僌巊彮逌偤輶栯脜蜏哊迶邘扵乻堬旕艅褕嬩鍝偊貐忬茟喐棫艈銉蓹薁繘軉澚惌邧貟酛茒媴嫄邍妴傆褑褤軏跀缊奫蝹鄖愪賱傊藴偺菑賳傤儎鐟趲蹔蹧艁趮幘樍諎謮賾蠌庂崱蠈熷譄吒偧鍘夈惉邅讝嶃偡虥虦傽慞蔁墇枛旐罀嫬袩悊詟謺讋乽桭葴嫃樼轃纼栚瑱掙衼嗭膱軄藢迣庢袟乿偫翐袠傂崻寘覟儨劕妐幒螤蹱茽偅诪荮粙葤詶僽噣笁曯斸迬殶跓膼跩塼僎壵漴娷諈迍棳斲諑斀斵謶灂蠗茊葘趦輺蓻惾葼鍐菆棷崒踿鎺栬晬鋷罇僔袏䐠
1+
娾僾壒鑀葊蓭儑垵貋嶅摮謷謸慠巼弝垻跁贁斒螌褩闆螁捠邫艕闁怉堢賲藵菢袌虣儤揹藣郥偝偹僃蛽翉楍倴桳撪輽埲偪楅螕聛貏邲苾袐弻煏蓽蜌廦覍徧艑脿幖儦藨謤贆諘虌彆邠儐虨臏抦昞棅偋傡剝袚缽僠瓟葧艊攃婇傪朁摻儏謲傖賶嶆蓸敇蓛箣憡偛艖詧祡袃訍蠆幨攙僝儃剷嵼幝閳譂讇锠僘謿巐仦蛼諃迧茞軙樄曟趻贂棦偁僜罉脭庱彨彲翄懘趩翀憃蹖揰搊菗椆摴貙幮藸傗滀蓫儊諔臅暷輲僢菙堾輴滣偆賰娕偨蠀嬨皉茦莿螆茐棇蓯聦婃欉謥脨趗憱顣鑹櫕缞嶉磪脺膬臎乼竴虘蟽軑軚艜蹛聸僤蓞贉簹艡欓讜儅趤壔翢艔軇瓙脦艠櫈袛藡拞菧聜偙僀嶳傎嵮蹎奌婰蜔訋蓧恎昳绖戜惵褋艓帄倲埬菄徚蕫迵戙枓脰嬻讟螙偳褍塅嵟逇敪埵軃尮偔崿詻僫讍奀峏栭厼趰誀茷傠蕟忛勫柉羳鐢蠜奿訉軓婏蕜杮鐨翂訜岎幩蕡羵僨膹偑僼鎽霻摓艂覂賵覅缹缻邞紨岪翇虙葍粰呒蜅撨峊袝偩覄褔蕧祴忋槩忓尷仠堈掆罁焹戅菒藳犵鎶輵挭拲羾莻袧褠茩苽箛唃傦脵崓僱詿柺覌輨泴悺罆茪僙椝槼螝膭蛫嶡蓘輥謴濄彍聝惈螒譀迒貥茠椃諕蠔悎傐抲蠚峆楁詥貈螛礉垎袔熇詪悙脝噷叿渹輷鍧纮垬娂翃粠葒綋翝晎闂闀葔虖軤膴謼螜虝嫮熩鍙婲搳撶螖諙諣褢褱貛寏藧巟偟葟熿艎趪詤愰婎幑褘撝蜖詯僡藱儶孈梡佸旤艧僟銈賷鐖覉忣揤偮庴塉檝螏鍓艥妀茍茤紒惎葪諅乫貑鎵忦蛺幏惤葌椷椾蕳熸瀐鐧虃弿謭蠒鐗葥諓翞螀傋弶謽茮虠嶕膲儌憿敿訆漖趭菨堦脻謯迼偼媫楬蜐蓵蠞蠘悈蛶褯兓惍巹蓳僸濅賮葏聙蟼曔僒褧奺欍崌跔艍諊僪蹫聥乬邭袓埾虡寠勮懅貗脧鎸埍菤臇覐趹傕蕝臄觼貜覠鍕晙懏擖欬偘埳惂邟囥犺鈧趷揢翗愙艐摼埪涳郀跍趶廤褲姱儈旝邼狅軖軠岲聧楏虁蹞聭蕢樻聵熴閫閸睏翋搚藞攋蠟婡崍賴葻儖懢攔讕襽郞艆蜋鎯蓢樃崀僗鐒蔂儽壨虆欙傫藟蠝鑸銇攂倰菞棃艃褵謧邌孋邐涖脷厤棙蛠蝷曆儮曞蠇壢藶觻欐讈梿覝聫褳聮螊謰蹥羷僆墚輬脼嶛膫屪廫賿蹘藔尦尞茢迾脟巤儠冧晽粦亃癛旈藰嬼翏廇蕯壠慺艛謱塿蓾艣鐪菉趢蹗鯥虂藘捛屢儢曫虊惀菕錀埨覙鏍儸攞欏曪洜嬤螞杩傌屘鏋槾澷庬莾茻軞乮蓩覒愗嚜脢槑徾嵄媺跊菛虋夣詸擟攠葞覔覛榓偭覕搣懱僶慜蠠姳慏詺謩擵懡眿蛨暯銆藦鏌怽畞莯幙艒鎿袦軜摨嬭褦螚暔擃儾怓巎抐脮埿聣抳儗儞聻伲迡堄嫟愵跈蹍蹨艌褭揑惗菍巕讘钀脌甯儜蕽挊羺鐞傉搙蹃藲鏂掱輫渒溿嗙褜奅斾蓜嶏葐梈旇翍壀脴擗鷿楄覑僄蠙聠呯帲幈缾蓱蛢輧敀娝擈菐贌巭迉桼蛣僛諆亝旂帺掑軝愭懠艩蠐邔婍忔湇罊蟿缼婜孯諐偂軡脥嗛傔儙輤蹡廧羻趬菬癄藮趫帩僺聺蛪鍥嶔菦嫀慬懄蠄笉梫菣撳埥夝剠殑葝檾掅儬宆儝藭丠媝蓲趥訅蛷髷菃翑葋鑺蝺迲奍峑婘葲烇虇崅夋衻袇袡媣儴讱屻岃訒軔梕茙峵媶搑褣螎嬫巆傇輮鍒蕠曘嗕偄輭膶虄僿褬濏譅桬儍翜翣邖挻脠軕搧羴晱訕傓僐敾樿蟺謪绱蕱袑蛥蠂屾葠訷蓡詵邥谉渖諗曋脤蜄瘮苼曻鉎鍟偗渻賸邿褷鍦乭姼枾媞煶諟鏉杸掓軗虪慡脽虒恖蕬螄柶蕼愯廀摉叜傁擻梀傃藗葰嵗鐩蕵傞摍溑褨鏁褟枱炲菭儓嬯忲惔墰墵燂罈藫貚傝僋蹚傏漟偒幍轁貣膯幐邆虅偍蕛趧蹏鍗悐揥趯屇庣蓨宨嬥覜聼邒閮聤娗脡蓪峝晍詷膧媮妵庩悇捈梌鍎迌貒剸鏄褖蓷藬尵蹪俀僓蹆軘臋袉跅媧嗗邷夞帵貦埦脕贃暀蛧迋葨詴嶶蓶鍏闈愇撱諉儰苿叞菋媦藯讏塭輼轀螡閺脗妏顐璺螉聬攚罋涹偓楃擭臒弙箼螐祦儛屼忢悞嵍邜傒翖嶲橀熻螇貕觽觿椺謵鎴蹝呬忥恄蕮虩傄翈敮蕸僊僲憸蹮妶蛝輱藖獮鍌幰攇峴晛缐僩僴壏膷鑲蠁缿宯虓翛膮虈郩涍詨斅峫翓讗藛缷偞偰僁褉嶰邤杺軐脪蛵曐侀讻詾賯诇脙鏅潃褎褏螑晇訏虗谞虛蕦諝譃呴偦詡怴欰藚吅弲梋鋗蕿蠉蜁嫙檈晅袨眴鏇袕壆瀥焄壎臐壦攳迿訙吖笌漄蕥偣綖詽虤壛巗椼褗覎葕傿椻暥嬊觾讞輰鍚岟炴傟懩傜摿暚邎宎抭偠袎覞艞讑僷曅歋擛悘毉侇迻宧巸弬栘袘訑貤蛦箷彛螔謻讉庡逘偯敼螘帠袣埶幆晹蛡跇嫕蓺槸艗貖賹藙贀虉讛訔訚崯朄讔憗懚粌偀愥绬嫈罃褮僌巊彮逌偤輶栯脜蜏哊迶邘扵乻堬旕艅褕嬩鍝偊貐忬茟喐棫艈銉蓹薁繘軉澚惌邧貟酛茒媴嫄邍妴傆褑褤軏跀缊奫蝹鄖愪賱傊藴偺菑賳傤儎鐟趲蹔蹧艁趮幘樍諎謮賾蠌庂崱蠈熷譄吒偧鍘夈惉邅讝嶃偡虥虦傽慞蔁墇枛旐罀嫬袩悊詟謺讋乽桭葴嫃樼轃纼栚瑱掙衼嗭膱軄藢迣庢袟乿偫翐袠傂崻寘覟儨劕妐幒螤蹱茽偅诪荮粙葤詶僽噣笁曯斸迬殶跓膼跩塼僎壵漴娷諈迍棳斲諑斀斵謶灂蠗茊葘趦輺蓻惾葼鍐菆棷崒踿鎺栬晬鋷罇僔袏䐠傤乯

0 commit comments

Comments
 (0)