Query parser generator refactor (#1006)

* Simplify select generation

* Refactor text generation

* Change optional argument

* Remove query-parser-templates.html

* Simplify prepare

* Simplify preview
This commit is contained in:
toasted-nutbread 2020-11-08 12:35:32 -05:00 committed by GitHub
parent 8cf10d685d
commit 12e6e37785
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 54 additions and 77 deletions

View File

@ -100,7 +100,6 @@ class Backend {
['clipboardGet', {async: true, contentScript: true, handler: this._onApiClipboardGet.bind(this)}], ['clipboardGet', {async: true, contentScript: true, handler: this._onApiClipboardGet.bind(this)}],
['clipboardGetImage', {async: true, contentScript: true, handler: this._onApiClipboardImageGet.bind(this)}], ['clipboardGetImage', {async: true, contentScript: true, handler: this._onApiClipboardImageGet.bind(this)}],
['getDisplayTemplatesHtml', {async: true, contentScript: true, handler: this._onApiGetDisplayTemplatesHtml.bind(this)}], ['getDisplayTemplatesHtml', {async: true, contentScript: true, handler: this._onApiGetDisplayTemplatesHtml.bind(this)}],
['getQueryParserTemplatesHtml', {async: true, contentScript: true, handler: this._onApiGetQueryParserTemplatesHtml.bind(this)}],
['getZoom', {async: true, contentScript: true, handler: this._onApiGetZoom.bind(this)}], ['getZoom', {async: true, contentScript: true, handler: this._onApiGetZoom.bind(this)}],
['getDefaultAnkiFieldTemplates', {async: false, contentScript: true, handler: this._onApiGetDefaultAnkiFieldTemplates.bind(this)}], ['getDefaultAnkiFieldTemplates', {async: false, contentScript: true, handler: this._onApiGetDefaultAnkiFieldTemplates.bind(this)}],
['getDictionaryInfo', {async: true, contentScript: false, handler: this._onApiGetDictionaryInfo.bind(this)}], ['getDictionaryInfo', {async: true, contentScript: false, handler: this._onApiGetDictionaryInfo.bind(this)}],
@ -594,10 +593,6 @@ class Backend {
return await this._fetchAsset('/mixed/display-templates.html'); return await this._fetchAsset('/mixed/display-templates.html');
} }
async _onApiGetQueryParserTemplatesHtml() {
return await this._fetchAsset('/bg/query-parser-templates.html');
}
_onApiGetZoom(params, sender) { _onApiGetZoom(params, sender) {
if (!sender || !sender.tab) { if (!sender || !sender.tab) {
return Promise.reject(new Error('Invalid tab')); return Promise.reject(new Error('Invalid tab'));

View File

@ -15,76 +15,78 @@
* along with this program. If not, see <https://www.gnu.org/licenses/>. * along with this program. If not, see <https://www.gnu.org/licenses/>.
*/ */
/* global
* HtmlTemplateCollection
* api
*/
class QueryParserGenerator { class QueryParserGenerator {
constructor() { createParseResult(terms, preview) {
this._templates = null; const type = preview ? 'preview' : 'normal';
}
async prepare() {
const html = await api.getQueryParserTemplatesHtml();
this._templates = new HtmlTemplateCollection(html);
}
createParseResult(terms, preview=false) {
const fragment = document.createDocumentFragment(); const fragment = document.createDocumentFragment();
for (const term of terms) { for (const term of terms) {
const termContainer = this._templates.instantiate(preview ? 'term-preview' : 'term'); const termNode = document.createElement('span');
termNode.className = 'query-parser-term';
termNode.dataset.type = type;
for (const segment of term) { for (const segment of term) {
if (!segment.text.trim()) { continue; } if (!segment.text.trim()) { continue; }
if (!segment.reading.trim()) { if (!segment.reading.trim()) {
termContainer.appendChild(this.createSegmentText(segment.text)); this._addSegmentText(segment.text, termNode);
} else { } else {
termContainer.appendChild(this.createSegment(segment)); termNode.appendChild(this._createSegment(segment));
} }
} }
fragment.appendChild(termContainer); fragment.appendChild(termNode);
}
return fragment;
}
createSegment(segment) {
const segmentContainer = this._templates.instantiate('segment');
const segmentTextContainer = segmentContainer.querySelector('.query-parser-segment-text');
const segmentReadingContainer = segmentContainer.querySelector('.query-parser-segment-reading');
segmentTextContainer.appendChild(this.createSegmentText(segment.text));
segmentReadingContainer.textContent = segment.reading;
return segmentContainer;
}
createSegmentText(text) {
const fragment = document.createDocumentFragment();
for (const chr of text) {
const charContainer = this._templates.instantiate('char');
charContainer.textContent = chr;
fragment.appendChild(charContainer);
} }
return fragment; return fragment;
} }
createParserSelect(parseResults, selectedParser) { createParserSelect(parseResults, selectedParser) {
const selectContainer = this._templates.instantiate('select'); const select = document.createElement('select');
select.className = 'query-parser-select form-control';
for (const parseResult of parseResults) { for (const parseResult of parseResults) {
const optionContainer = this._templates.instantiate('select-option'); const option = document.createElement('option');
optionContainer.value = parseResult.id; option.className = 'query-parser-select-option';
option.value = parseResult.id;
switch (parseResult.source) { switch (parseResult.source) {
case 'scanning-parser': case 'scanning-parser':
optionContainer.textContent = 'Scanning parser'; option.textContent = 'Scanning parser';
break; break;
case 'mecab': case 'mecab':
optionContainer.textContent = `MeCab: ${parseResult.dictionary}`; option.textContent = `MeCab: ${parseResult.dictionary}`;
break; break;
default: default:
optionContainer.textContent = 'Unrecognized dictionary'; option.textContent = 'Unrecognized dictionary';
break; break;
} }
optionContainer.defaultSelected = selectedParser === parseResult.id; option.defaultSelected = selectedParser === parseResult.id;
selectContainer.appendChild(optionContainer); select.appendChild(option);
}
return select;
}
// Private
_createSegment(segment) {
const segmentNode = document.createElement('ruby');
segmentNode.className = 'query-parser-segment';
const textNode = document.createElement('span');
textNode.className = 'query-parser-segment-text';
const readingNode = document.createElement('rt');
readingNode.className = 'query-parser-segment-reading';
segmentNode.appendChild(textNode);
segmentNode.appendChild(readingNode);
this._addSegmentText(segment.text, textNode);
readingNode.textContent = segment.reading;
return segmentNode;
}
_addSegmentText(text, container) {
for (const character of text) {
const node = document.createElement('span');
node.className = 'query-parser-char';
node.textContent = character;
container.appendChild(node);
} }
return selectContainer;
} }
} }

View File

@ -44,8 +44,7 @@ class QueryParser extends EventDispatcher {
}); });
} }
async prepare() { prepare() {
await this._queryParserGenerator.prepare();
this._textScanner.prepare(); this._textScanner.prepare();
this._textScanner.on('searched', this._onSearched.bind(this)); this._textScanner.on('searched', this._onSearched.bind(this));
} }
@ -125,13 +124,9 @@ class QueryParser extends EventDispatcher {
} }
_setPreview(text) { _setPreview(text) {
const previewTerms = []; const terms = [[{text, reading: ''}]];
for (let i = 0, ii = text.length; i < ii; i += 2) {
const tempText = text.substring(i, i + 2);
previewTerms.push([{text: tempText, reading: ''}]);
}
this._queryParser.textContent = ''; this._queryParser.textContent = '';
this._queryParser.appendChild(this._queryParserGenerator.createParseResult(previewTerms, true)); this._queryParser.appendChild(this._queryParserGenerator.createParseResult(terms, true));
} }
_renderParserSelect() { _renderParserSelect() {
@ -148,6 +143,6 @@ class QueryParser extends EventDispatcher {
const parseResult = this._getParseResult(); const parseResult = this._getParseResult();
this._queryParser.textContent = ''; this._queryParser.textContent = '';
if (!parseResult) { return; } if (!parseResult) { return; }
this._queryParser.appendChild(this._queryParserGenerator.createParseResult(parseResult.content)); this._queryParser.appendChild(this._queryParserGenerator.createParseResult(parseResult.content, false));
} }
} }

View File

@ -1,11 +0,0 @@
<!DOCTYPE html><html><head></head><body>
<template id="term-template"><span class="query-parser-term" data-type="normal"></span></template>
<template id="term-preview-template"><span class="query-parser-term" data-type="preview"></span></template>
<template id="segment-template"><ruby class="query-parser-segment"><span class="query-parser-segment-text"></span><rt class="query-parser-segment-reading"></rt></ruby></template>
<template id="char-template"><span class="query-parser-char"></span></template>
<template id="select-template"><select class="query-parser-select form-control"></select></template>
<template id="select-option-template"><option class="query-parser-select-option"></option></template>
</body></html>

View File

@ -137,10 +137,6 @@ const api = (() => {
return this._invoke('getDisplayTemplatesHtml'); return this._invoke('getDisplayTemplatesHtml');
} }
getQueryParserTemplatesHtml() {
return this._invoke('getQueryParserTemplatesHtml');
}
getZoom() { getZoom() {
return this._invoke('getZoom'); return this._invoke('getZoom');
} }

View File

@ -164,7 +164,7 @@ class Display extends EventDispatcher {
this._updateMode(); this._updateMode();
this._setInteractive(true); this._setInteractive(true);
await this._displayGenerator.prepare(); await this._displayGenerator.prepare();
await this._queryParser.prepare(); this._queryParser.prepare();
this._history.prepare(); this._history.prepare();
this._history.on('stateChanged', this._onStateChanged.bind(this)); this._history.on('stateChanged', this._onStateChanged.bind(this));
this._queryParser.on('searched', this._onQueryParserSearch.bind(this)); this._queryParser.on('searched', this._onQueryParserSearch.bind(this));