// 字典对象 const Word = require("./Word") const WordGroup = require("./WordGroup") const {shakeDom, log, shakeDomFocus} = require('./Utility') const os = require('os') class Dict { constructor(fileContent, fileName, filePath) { this.dictTypeName = 'Dict' this.filePath = filePath // 文件路径 this.fileName = fileName // 文件名字 this.header = null // 文件头部内容 this.wordsOrigin = [] // 文件词条数组 this.lastIndex = 0 // 最后一个Word Index 的值,用于新添加词时,作为唯一的 id 传入 this.lastGroupIndex = 0 // 最后一个WordGroup Index 的值,用于新添加词时,作为唯一的 id 传入 this.isGroupMode = false // 识别码表是否为分组形式的 let indexEndOfHeader = fileContent.indexOf('...') if (indexEndOfHeader < 0){ log('文件格式错误,没有 ... 这一行') } else { this.indexEndOfHeader = indexEndOfHeader + 3 this.header = fileContent.substring(0, this.indexEndOfHeader) this.isGroupMode = this.header.includes('dict_grouped: true') // 根据有没有这一段文字进行判断,是否为分组形式的码表 let body = fileContent.substring(this.indexEndOfHeader) this.wordsOrigin = this.isGroupMode? this.getDictWordsInGroupMode(body): this.getDictWordsInNormalMode(body) } } // 总的词条数量 get countDictOrigin(){ if (this.isGroupMode){ let countOrigin = 0 this.wordsOrigin.forEach(group => { countOrigin = countOrigin + group.dict.length }) return countOrigin } else { return this.wordsOrigin.length } } // 返回所有 word getDictWordsInNormalMode(fileContent){ let startPoint = new Date().getTime() let EOL = this.getFileEOLFrom(fileContent) let lines = fileContent.split(EOL) // 拆分词条与编码成单行 this.lastIndex = lines.length let linesValid = lines.filter(item => item.indexOf('\t') > -1) // 选取包含 \t 的行 let words = [] linesValid.forEach((item, index) => { let currentWord = getWordFromLine(index, item) words.push(currentWord) // 获取词条 }) log(`处理yaml码表文件:完成,共:${words.length } ${this.isGroupMode? '组': '条'},用时 ${new Date().getTime() - startPoint} ms`) return words } // 返回 word 分组 getDictWordsInGroupMode(fileContent){ let startPoint = new Date().getTime() let EOL = this.getFileEOLFrom(fileContent) let lines = fileContent.split(EOL) // 拆分词条与编码成单行 let wordsGroup = [] // 总分组 let temp = null // 第一个分组 let lastItemIsEmptyLine = false // 上一条是空,用于循环中判断是否需要新起一个 WordGroup this.lastIndex = lines.length lines.forEach((item, index) => { if (item.startsWith('##')) { // 注释分组 if (temp && temp.groupName) { // 如果上一个已经有名字了,说明需要保存 wordsGroup.push(temp) } temp = new WordGroup(this.lastGroupIndex++, item.substring(3).trim()) lastItemIsEmptyLine = false } else if (item.indexOf('\t') > -1) { // 是词条 if (!temp){ // 第一行是词条时,没有分组名时 temp = new WordGroup(this.lastGroupIndex++) } temp.dict.push(getWordFromLine(index, item)) lastItemIsEmptyLine = false } else if (item.startsWith('#')) { // 注释 log(item) lastItemIsEmptyLine = false } else { // 为空行时 if (lastItemIsEmptyLine){ // 上行和本行都是空行 } else { if (temp){ temp.groupName = temp.groupName || '未命名' wordsGroup.push(temp) temp = new WordGroup(this.lastGroupIndex++) } } lastItemIsEmptyLine = true } }) log(`处理yaml码表文件:完成,共:${wordsGroup.length } ${this.isGroupMode? '组': '条'},用时 ${new Date().getTime() - startPoint} ms`) if (temp){ if (temp.dict.length > 0){ wordsGroup.push(temp) // 加上最后一个 } return wordsGroup } else { return [] // 文件内容为空时 } } // 判断码表文件的换行符是 \r\n 还是 \n getFileEOLFrom(fileContent){ if(fileContent.indexOf('\r\n') > 0){ return '\r\n' } else { return '\n' } } // 排序 sort(groupIndex){ let startPoint = new Date().getTime() if (this.isGroupMode){ // group mode if (groupIndex !== -1){ // -1 代表全部 this.wordsOrigin[groupIndex].dict.sort((a,b) => a.code < b.code ? -1: 1) } else { this.wordsOrigin.forEach(group => { group.dict.sort((a,b) => a.code < b.code ? -1: 1) }) } } else { this.wordsOrigin.sort((a,b) => a.code < b.code ? -1: 1) } log(`Sort 用时 ${new Date().getTime() - startPoint} ms`) } /** * 添加新 Word * @param word Word * @param groupIndex Number */ addNewWord(word, groupIndex){ if(this.isGroupMode){ if (groupIndex !== -1){ this.wordsOrigin[groupIndex].dict.push(word) } else { let newWordGroup = new WordGroup(this.lastGroupIndex++,'- 未命名 -',[word]) this.wordsOrigin.unshift(newWordGroup) // 添加到第一组 } } else { this.addWordToDictInOrder(word) } this.lastIndex = this.lastIndex + 1 // 新加的词添加后, lastIndex + 1 } // 依次序添加 words addWordsInOrder(words, groupIndex){ let startPoint = new Date().getTime() if (this.isGroupMode && groupIndex !== -1){ this.addWordToDictInOrderWithGroup(words, groupIndex) } else { words.forEach(word => { this.addWordToDictInOrder(word) }) } log(`添加 ${words.length } 条词条到指定码表, 用时 ${new Date().getTime() - startPoint} ms`) } // 依次序添加 word addWordToDictInOrder(word){ let insetPosition = null // 插入位置 index for (let i=0; i= this.wordsOrigin[i] && word.code <= this.wordsOrigin[i+1].code){ insetPosition = i + 1 break } } if (!insetPosition){ // 没有匹配到任何位置,添加到结尾 insetPosition = this.wordsOrigin.length } let wordInsert = word.clone() // 断开与别一个 dict 的引用链接,新建一个 word 对象,不然两个 dict 引用同一个 word wordInsert.setId(this.lastIndex++) // 给新的 words 一个新的唯一 id this.wordsOrigin.splice(insetPosition, 0, wordInsert) } // 依次序添加 word groupMode addWordToDictInOrderWithGroup(words, groupIndex){ let dictWords = this.wordsOrigin[groupIndex].dict log('TODO: add to group') words.forEach(word => { let insetPosition = null // 插入位置 index for (let i=0; i= dictWords[i] && word.code <= dictWords[i+1].code){ insetPosition = i + 1 break } } if (!insetPosition){ // 没有匹配到任何位置,添加到结尾 insetPosition = dictWords.length } let wordInsert = word.clone() // 断开与别一个 dict 的引用链接,新建一个 word 对象,不然两个 dict 引用同一个 word wordInsert.id = dictWords.length + 1 // 给新的 words 一个新的唯一 id dictWords.splice(insetPosition, 0, wordInsert) }) } // 删除词条 deleteWords(wordIdSet, isDeleteInSelf){ // isDeleteInSelf 在移动词条到自己分组时使用,不删除空的分组 if (this.isGroupMode){ let deleteGroupIds = [] // 记录 words 为 0 的 group,最后删除分组 this.wordsOrigin.forEach((group, index) => { group.dict = group.dict.filter(item => !wordIdSet.has(item.id)) if (group.dict.length === 0){ deleteGroupIds.push(index) } }) // config: 是否删除空的分组 if (!isDeleteInSelf){ this.wordsOrigin = this.wordsOrigin.filter((group, index) => !deleteGroupIds.includes(index)) } } else { this.wordsOrigin = this.wordsOrigin.filter(item => !wordIdSet.has(item.id)) } } addGroupBeforeId(groupIndex){ this.wordsOrigin.splice(groupIndex,0,new WordGroup(this.lastGroupIndex++,'',[],true)) } // 分组模式:删除分组 deleteGroup(groupId){ log('要删除的分组 id: ',groupId) this.wordsOrigin = this.wordsOrigin.filter(group => group.id !== groupId) } // 转为 yaml String toYamlString(){ let yamlBody = '' if (this.isGroupMode){ this.wordsOrigin.forEach(group => { let tempGroupString = '' tempGroupString = tempGroupString + `## ${group.groupName}${os.EOL}` // + groupName group.dict.forEach(item =>{ tempGroupString = tempGroupString + item.toYamlString() + os.EOL }) yamlBody = yamlBody + tempGroupString + os.EOL // 每组的末尾加个空行 }) return this.header + os.EOL + yamlBody } else { let yamlBody = '' this.wordsOrigin.forEach(item =>{ yamlBody = yamlBody + item.toYamlString() + os.EOL }) return this.header + os.EOL + yamlBody } } // 在 origin 中调换两个词条的位置 exchangePositionInOrigin(word1, word2){ // 确保 word1 在前 if (parseInt(word1.id) > parseInt(word2.id)){ let temp = word1 word1 = word2 word2 = temp } for(let i=0; i 2 ? wordArray[2] : null return new Word(index, code, word, priority) } module.exports = Dict