module.exports = class Definitions { constructor (editor) { this.editor = editor this.alreadyAlerted = '' this.init() } init () { this.definitions = {} this.definitionParagraphsInClause = [] this.usedDefinitions = {} this.definedDefinitions = {} this.undefinedDefinitions = {} this.otherDefinitions = {} this.definitionClauseContent = '' this.definitionClauseEndIndex = null } boot () { this.init() const success = this.getDefinitionClause() if (!success) { return } this.setUsedDefinitions() this.setDefinitions() this.setDefinedDefinitions() } getDefinitionClause () { const content = this.editor.getText() const reg = /(# Definitions)([a-z]*[A-Z]*[ ]*)*/g const result = [...content.matchAll(reg)] if (result.length === 0) { const message = 'There is no definition clause defined.' if (!this.alreadyAlerted || message !== this.alreadyAlerted) { alert(message) this.alreadyAlerted = 'message' } return false } if (result.length > 1) { const message = `There are ${result.length} definition clauses. There should only be one.` if (!this.alreadyAlerted || message !== this.alreadyAlerted) { alert(message) this.alreadyAlerted = message } return false } // Definition clause index const index = result[0].index let text = content.substring(index) // Text containing the Definition clause heading let startText = result[0][0] this.definitionClauseEndIndex = index + startText.length // Remove the text containing the Definition clause heading so we can look for the next clause text = text.substring(startText.length) const nextClauseReg = /[^#]# ([a-z]*[A-Z]*)*/g const nextClauseResult = [...text.matchAll(nextClauseReg)] let nextClauseIndex = nextClauseResult.length > 0 ? nextClauseResult[0].index : text.length text = text.substring(0, nextClauseIndex) // Build the full content of the Definition clause this.definitionClauseContent = startText.concat(text) return true } setUsedDefinitions () { const content = this.editor.getText() const reg = /_([^_\n]*)_/g for (let match of content.matchAll(reg)) { if (!match[1]) { continue } if (!this.usedDefinitions.hasOwnProperty(match[1])) { this.usedDefinitions[match[1]] = [] } this.usedDefinitions[match[1]].push(match.index) } } setDefinitions () { const content = this.editor.getText() const reg = /\*\*([^**\n]*)\*\*/g for (let match of content.matchAll(reg)) { if (!match[1]) { continue } if (!this.definitions.hasOwnProperty(match[1])) { this.definitions[match[1]] = [] } this.definitions[match[1]].push(match.index) } } setDefinedDefinitions () { const regex = /## (.)*\n/g const definitionParagraphsInClause = this.definitionClauseContent.matchAll(regex) const definitionsMapper = JSON.parse(JSON.stringify(this.definitions)) for (let definitionParagraph of definitionParagraphsInClause) { if (definitionParagraph && definitionParagraph[0]) { this.definitionParagraphsInClause.push(definitionParagraph) let definitionContent = definitionParagraph[0] let found = false for (let definition of Object.keys(definitionsMapper)) { const definitionToSearch = `**${definition}** means ` let index = definitionContent.indexOf(definitionToSearch) if (index !== -1) { let definitionExtracted = definitionContent.substring(index + definitionToSearch.length) definitionExtracted = definitionExtracted.replace('[', '') definitionExtracted = definitionExtracted.replace(']', '') definitionExtracted = definitionExtracted.trim() if (definitionExtracted.length > 0) { this.definedDefinitions[definition] = definitionExtracted } else { this.undefinedDefinitions[definition] = true } delete definitionsMapper[definition] found = true break } // let results = definitionContent.match(new RegExp(`(${definition} means )([[(.)*]])`)) // if (results && results[0]) { // // // } } if (!found) { this.otherDefinitions[definitionContent] = true } } } if (Object.keys(definitionsMapper).length > 0) { this.insertDefinitions(Object.keys(definitionsMapper)) // Refresh this because it contains more definition paragraphs this.getDefinitionClause() } } insertDefinitions (definitions) { let currentRow = this.getRowPositionToInsertDefinitions() const currentPosition = this.editor.getCursorBufferPosition() for (let definition of definitions) { this.editor.setCursorBufferPosition([currentRow, 0]) this.editor.insertText(`## **${definition}** means []\n`) currentRow = currentRow + 1 this.undefinedDefinitions[definition] = true } this.editor.setCursorBufferPosition(currentPosition) } getRowPositionToInsertDefinitions () { const content = this.editor.getText() const reg = /\n/g const results = content.matchAll(reg) let linesCount = 0 for (let result of results) { if (result.index === this.definitionClauseEndIndex) { return linesCount + 1 + this.definitionParagraphsInClause.length } else { linesCount = linesCount + 1 } } return linesCount } getDefinedDefinitions () { return Object.keys(this.definedDefinitions) } }