diff --git a/app/static/js/corpus-analysis/query-builder/query-builder.js b/app/static/js/corpus-analysis/query-builder/query-builder.js index d248cbb1af451d618f27488a1bf869f5065c32fc..adca9e13eb1a79ce90c477d1df4b54111567d762 100644 --- a/app/static/js/corpus-analysis/query-builder/query-builder.js +++ b/app/static/js/corpus-analysis/query-builder/query-builder.js @@ -99,18 +99,14 @@ nopaque.corpus_analysis.query_builder.QueryBuilder = class QueryBuilder { // Ensures that metadata is always at the end of the query and if an index is given, inserts the query chip at the given index and if there is a closing tag, inserts the query chip before the closing tag. this.removePlaceholder(); - let lastChild = this.elements.queryInputField.lastChild; - let isLastChildTextAnnotation = lastChild && lastChild.dataset.type === 'text-annotation'; if (!index) { let closingTagElement = this.elements.queryInputField.querySelector('[data-closing-tag="true"]'); if (closingTagElement) { index = Array.from(this.elements.queryInputField.children).indexOf(closingTagElement); } } - if (dataType !== 'text-annotation' && index) { + if (index) { this.elements.queryInputField.insertBefore(queryChipElement, this.elements.queryChipElements[index]); - } else if (dataType !== 'text-annotation' && isLastChildTextAnnotation) { - this.elements.queryInputField.insertBefore(queryChipElement, lastChild); } else { this.elements.queryInputField.appendChild(queryChipElement); } @@ -149,9 +145,6 @@ nopaque.corpus_analysis.query_builder.QueryBuilder = class QueryBuilder { case 'start-entity': this.extensions.structuralAttributeBuilderFunctions.editStartEntityChipElement(queryChipElement); break; - case 'text-annotation': - this.extensions.structuralAttributeBuilderFunctions.editTextAnnotationChipElement(queryChipElement); - break; case 'token': let queryElementsContent = this.extensions.tokenAttributeBuilderFunctions.prepareTokenQueryElementsContent(queryChipElement); this.extensions.tokenAttributeBuilderFunctions.editTokenChipElement(queryElementsContent); @@ -329,7 +322,7 @@ nopaque.corpus_analysis.query_builder.QueryBuilder = class QueryBuilder { if (dropdownId === 'corpus-analysis-concordance-token-incidence-modifiers-dropdown') { button.addEventListener('click', () => this.tokenIncidenceModifierHandler(button.dataset.token, button.innerHTML)); } else if (dropdownId === 'corpus-analysis-concordance-character-incidence-modifiers-dropdown') { - button.addEventListener('click', () => this.characterIncidenceModifierHandler(button)); + button.addEventListener('click', () => this.extensions.tokenAttributeBuilderFunctions.characterIncidenceModifierHandler(button)); } }); } @@ -360,7 +353,7 @@ nopaque.corpus_analysis.query_builder.QueryBuilder = class QueryBuilder { let expertModeInputFieldValue = document.querySelector('#corpus-analysis-concordance-form-query').value; let chipElements = this.parseTextToChip(expertModeInputFieldValue); let closingTagElements = ['end-sentence', 'end-entity']; - let editableElements = ['start-entity', 'text-annotation', 'token']; + let editableElements = ['start-entity', 'token']; for (let chipElement of chipElements) { let isClosingTag = closingTagElements.includes(chipElement['type']); let isEditable = editableElements.includes(chipElement['type']); @@ -393,11 +386,7 @@ nopaque.corpus_analysis.query_builder.QueryBuilder = class QueryBuilder { pretty: 'Entity End', type: 'end-entity' }, - ':: ?match\\.text_[A-Za-z]+="[^"]+"': { - pretty: '', - type: 'text-annotation' - }, - '\\[(word|lemma|pos|simple_pos)=(("[^"]+")|(\\u0027[^\\u0027]+\\u0027)) ?(%c)? ?((\\&|\\|) ?(word|lemma|pos|simple_pos)=(("[^"]+")|(\\u0027[^\\u0027]+\\u0027)) ?(%c)? ?)*\\]': { + '\\[(word|lemma|pos|simple_pos)=("(?:[^"\\\\]|\\\\")*") ?(%c)? ?((\\&|\\|) ?(word|lemma|pos|simple_pos)=("(?:[^"\\\\]|\\\\")*") ?(%c)? ?)*\\]': { pretty: '', type: 'token' }, @@ -450,14 +439,8 @@ nopaque.corpus_analysis.query_builder.QueryBuilder = class QueryBuilder { case ':: ?match\\.text_[A-Za-z]+="[^"]+"': prettyText = stringElement.replace(/:: ?match\.text_|"|"/g, ''); break; - case '\\[(word|lemma|pos|simple_pos)=(("[^"]+")|(\\u0027[^\\u0027]+\\u0027)) ?(%c)? ?((\\&|\\|) ?(word|lemma|pos|simple_pos)=(("[^"]+")|(\\u0027[^\\u0027]+\\u0027)) ?(%c)? ?)*\\]': - let doubleQuotes = /(word|lemma|pos|simple_pos)="[^"]+"/gi; - let singleQuotes = /(word|lemma|pos|simple_pos)='[^']+'/gi; - if (doubleQuotes.exec(stringElement)) { - prettyText = stringElement.replace(/^\[|\]$|"/g, ''); - } else if (singleQuotes.exec(stringElement)) { - prettyText = stringElement.replace(/^\[|\]$|'/g, ''); - } + case '\\[(word|lemma|pos|simple_pos)=("(?:[^"\\\\]|\\\\")*") ?(%c)? ?((\\&|\\|) ?(word|lemma|pos|simple_pos)=("(?:[^"\\\\]|\\\\")*") ?(%c)? ?)*\\]': + prettyText = stringElement.replace(/^\[|\]$|(?<!\\)"/g, ''); prettyText = prettyText.replace(/\&/g, ' and ').replace(/\|/g, ' or '); break; case '(?<!\\[) ?\\{[0-9]+} ?(?![^\\]]\\])': diff --git a/app/static/js/corpus-analysis/query-builder/token-attribute-builder-functions.js b/app/static/js/corpus-analysis/query-builder/token-attribute-builder-functions.js index 14ea5f5fafd738c2fbfa8e72a152918b8ba17de4..02a23f0e91883d7ecd2c95e9d68f7ebbbd154af7 100644 --- a/app/static/js/corpus-analysis/query-builder/token-attribute-builder-functions.js +++ b/app/static/js/corpus-analysis/query-builder/token-attribute-builder-functions.js @@ -285,8 +285,8 @@ nopaque.corpus_analysis.query_builder.TokenAttributeBuilderFunctions = class Tok } prepareTokenQueryElementsContent(queryChipElement) { - //this regex searches for word or lemma or pos or simple_pos="any string within single or double quotes" followed by one or no ignore case markers, followed by one or no condition characters. - let regex = new RegExp('(word|lemma|pos|simple_pos)=(("[^"]+")|(\\\\u0027[^\\\\u0027]+\\\\u0027)) ?(%c)? ?(\\&|\\|)?', 'gm'); + //this regex searches for word or lemma or pos or simple_pos="any string (also quotation marks escaped by backslash) within double quotes" followed by one or no ignore case markers, followed by one or no condition characters. + let regex = new RegExp('(word|lemma|pos|simple_pos)=("(?:[^"\\\\]|\\\\")*") ?(%c)? ?(\\&|\\|)?', 'gm'); let m; let queryElementsContent = []; while ((m = regex.exec(queryChipElement.dataset.query)) !== null) { @@ -299,7 +299,7 @@ nopaque.corpus_analysis.query_builder.TokenAttributeBuilderFunctions = class Tok if (tokenAttr === 'pos') { tokenAttr = 'english-pos'; } - let tokenValue = m[2].replace(/"|'/g, ''); + let tokenValue = m[2].replace(/(?<!\\)"/g, ''); let ignoreCase = false; let condition = undefined; m.forEach((match) => {