From 8b07a23de95ded3e6af93c78ab4f7f70cc449ea0 Mon Sep 17 00:00:00 2001 From: toasted-nutbread Date: Sun, 15 Mar 2020 17:02:34 -0400 Subject: [PATCH 1/7] Rename context to details --- ext/bg/js/backend.js | 6 +++--- ext/mixed/js/api.js | 4 ++-- ext/mixed/js/display.js | 6 +++--- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/ext/bg/js/backend.js b/ext/bg/js/backend.js index 1e8c979f..e7ae7026 100644 --- a/ext/bg/js/backend.js +++ b/ext/bg/js/backend.js @@ -455,7 +455,7 @@ class Backend { return results; } - async _onApiDefinitionAdd({definition, mode, context, optionsContext}) { + async _onApiDefinitionAdd({definition, mode, details, optionsContext}) { const options = this.getOptions(optionsContext); const templates = this.defaultAnkiFieldTemplates; @@ -468,11 +468,11 @@ class Backend { ); } - if (context && context.screenshot) { + if (details && details.screenshot) { await this._injectScreenshot( definition, options.anki.terms.fields, - context.screenshot + details.screenshot ); } diff --git a/ext/mixed/js/api.js b/ext/mixed/js/api.js index 0ab07039..df6a93f5 100644 --- a/ext/mixed/js/api.js +++ b/ext/mixed/js/api.js @@ -53,8 +53,8 @@ function apiKanjiFind(text, optionsContext) { return _apiInvoke('kanjiFind', {text, optionsContext}); } -function apiDefinitionAdd(definition, mode, context, optionsContext) { - return _apiInvoke('definitionAdd', {definition, mode, context, optionsContext}); +function apiDefinitionAdd(definition, mode, details, optionsContext) { + return _apiInvoke('definitionAdd', {definition, mode, details, optionsContext}); } function apiDefinitionsAddable(definitions, modes, optionsContext) { diff --git a/ext/mixed/js/display.js b/ext/mixed/js/display.js index 4a71efe0..8587657f 100644 --- a/ext/mixed/js/display.js +++ b/ext/mixed/js/display.js @@ -752,15 +752,15 @@ class Display { try { this.setSpinnerVisible(true); - const context = {}; + const details = {}; if (this.noteUsesScreenshot(mode)) { const screenshot = await this.getScreenshot(); if (screenshot) { - context.screenshot = screenshot; + details.screenshot = screenshot; } } - const noteId = await apiDefinitionAdd(definition, mode, context, this.getOptionsContext()); + const noteId = await apiDefinitionAdd(definition, mode, details, this.getOptionsContext()); if (noteId) { const index = this.definitions.indexOf(definition); const adderButton = this.adderButtonFind(index, mode); From 059db280bba858a3cab3a542aef13f19737aaf6e Mon Sep 17 00:00:00 2001 From: toasted-nutbread Date: Sun, 15 Mar 2020 17:13:00 -0400 Subject: [PATCH 2/7] Add custom context object for note creation --- ext/bg/js/anki-note-builder.js | 9 +++++---- ext/bg/js/backend.js | 8 ++++---- ext/bg/js/settings/anki-templates.js | 3 ++- ext/mixed/js/api.js | 8 ++++---- ext/mixed/js/display.js | 8 ++++++-- 5 files changed, 21 insertions(+), 15 deletions(-) diff --git a/ext/bg/js/anki-note-builder.js b/ext/bg/js/anki-note-builder.js index d0ff8205..51022da3 100644 --- a/ext/bg/js/anki-note-builder.js +++ b/ext/bg/js/anki-note-builder.js @@ -21,7 +21,7 @@ class AnkiNoteBuilder { this._renderTemplate = renderTemplate; } - async createNote(definition, mode, options, templates) { + async createNote(definition, mode, context, options, templates) { const isKanji = (mode === 'kanji'); const tags = options.anki.tags; const modeOptions = isKanji ? options.anki.kanji : options.anki.terms; @@ -35,7 +35,7 @@ class AnkiNoteBuilder { }; for (const [fieldName, fieldValue] of modeOptionsFieldEntries) { - note.fields[fieldName] = await this.formatField(fieldValue, definition, mode, options, templates, null); + note.fields[fieldName] = await this.formatField(fieldValue, definition, mode, context, options, templates, null); } if (!isKanji && definition.audio) { @@ -60,7 +60,7 @@ class AnkiNoteBuilder { return note; } - async formatField(field, definition, mode, options, templates, errors=null) { + async formatField(field, definition, mode, context, options, templates, errors=null) { const data = { marker: null, definition, @@ -69,7 +69,8 @@ class AnkiNoteBuilder { modeTermKanji: mode === 'term-kanji', modeTermKana: mode === 'term-kana', modeKanji: mode === 'kanji', - compactGlossaries: options.general.compactGlossaries + compactGlossaries: options.general.compactGlossaries, + context }; const pattern = /\{([\w-]+)\}/g; return await AnkiNoteBuilder.stringReplaceAsync(field, pattern, async (g0, marker) => { diff --git a/ext/bg/js/backend.js b/ext/bg/js/backend.js index e7ae7026..d4c822ca 100644 --- a/ext/bg/js/backend.js +++ b/ext/bg/js/backend.js @@ -455,7 +455,7 @@ class Backend { return results; } - async _onApiDefinitionAdd({definition, mode, details, optionsContext}) { + async _onApiDefinitionAdd({definition, mode, context, details, optionsContext}) { const options = this.getOptions(optionsContext); const templates = this.defaultAnkiFieldTemplates; @@ -476,11 +476,11 @@ class Backend { ); } - const note = await this.ankiNoteBuilder.createNote(definition, mode, options, templates); + const note = await this.ankiNoteBuilder.createNote(definition, mode, context, options, templates); return this.anki.addNote(note); } - async _onApiDefinitionsAddable({definitions, modes, optionsContext}) { + async _onApiDefinitionsAddable({definitions, modes, context, optionsContext}) { const options = this.getOptions(optionsContext); const templates = this.defaultAnkiFieldTemplates; const states = []; @@ -489,7 +489,7 @@ class Backend { const notes = []; for (const definition of definitions) { for (const mode of modes) { - const note = await this.ankiNoteBuilder.createNote(definition, mode, options, templates); + const note = await this.ankiNoteBuilder.createNote(definition, mode, context, options, templates); notes.push(note); } } diff --git a/ext/bg/js/settings/anki-templates.js b/ext/bg/js/settings/anki-templates.js index c5222d30..88bca024 100644 --- a/ext/bg/js/settings/anki-templates.js +++ b/ext/bg/js/settings/anki-templates.js @@ -99,10 +99,11 @@ async function ankiTemplatesValidate(infoNode, field, mode, showSuccessResult, i const definition = await ankiTemplatesValidateGetDefinition(text, optionsContext); if (definition !== null) { const options = await apiOptionsGet(optionsContext); + const context = {}; let templates = options.anki.fieldTemplates; if (typeof templates !== 'string') { templates = await apiGetDefaultAnkiFieldTemplates(); } const ankiNoteBuilder = new AnkiNoteBuilder({renderTemplate: apiTemplateRender}); - result = await ankiNoteBuilder.formatField(field, definition, mode, options, templates, exceptions); + result = await ankiNoteBuilder.formatField(field, definition, mode, context, options, templates, exceptions); } } catch (e) { exceptions.push(e); diff --git a/ext/mixed/js/api.js b/ext/mixed/js/api.js index df6a93f5..feec94df 100644 --- a/ext/mixed/js/api.js +++ b/ext/mixed/js/api.js @@ -53,12 +53,12 @@ function apiKanjiFind(text, optionsContext) { return _apiInvoke('kanjiFind', {text, optionsContext}); } -function apiDefinitionAdd(definition, mode, details, optionsContext) { - return _apiInvoke('definitionAdd', {definition, mode, details, optionsContext}); +function apiDefinitionAdd(definition, mode, context, details, optionsContext) { + return _apiInvoke('definitionAdd', {definition, mode, context, details, optionsContext}); } -function apiDefinitionsAddable(definitions, modes, optionsContext) { - return _apiInvoke('definitionsAddable', {definitions, modes, optionsContext}); +function apiDefinitionsAddable(definitions, modes, context, optionsContext) { + return _apiInvoke('definitionsAddable', {definitions, modes, context, optionsContext}); } function apiNoteView(noteId) { diff --git a/ext/mixed/js/display.js b/ext/mixed/js/display.js index 8587657f..ecf92013 100644 --- a/ext/mixed/js/display.js +++ b/ext/mixed/js/display.js @@ -760,7 +760,7 @@ class Display { } } - const noteId = await apiDefinitionAdd(definition, mode, details, this.getOptionsContext()); + const noteId = await apiDefinitionAdd(definition, mode, this._getNoteContext(), details, this.getOptionsContext()); if (noteId) { const index = this.definitions.indexOf(definition); const adderButton = this.adderButtonFind(index, mode); @@ -908,7 +908,7 @@ class Display { async getDefinitionsAddable(definitions, modes) { try { - return await apiDefinitionsAddable(definitions, modes, this.getOptionsContext()); + return await apiDefinitionsAddable(definitions, modes, this._getNoteContext(), this.getOptionsContext()); } catch (e) { return []; } @@ -934,6 +934,10 @@ class Display { return (typeof key === 'string' ? (key.length === 1 ? key.toUpperCase() : key) : ''); } + _getNoteContext() { + return {}; + } + async _getAudioUri(definition, source) { const optionsContext = this.getOptionsContext(); return await apiAudioGetUri(definition, source, optionsContext); From 4011a091b69475e7096d80103b4dad9aa1b8d80b Mon Sep 17 00:00:00 2001 From: toasted-nutbread Date: Sun, 15 Mar 2020 17:32:31 -0400 Subject: [PATCH 3/7] Add support for {document-title} --- README.md | 2 ++ ext/bg/data/default-anki-field-templates.handlebars | 4 ++++ ext/bg/js/options.js | 9 +++++++++ ext/bg/js/settings/anki-templates.js | 6 +++++- ext/mixed/js/display.js | 6 +++++- 5 files changed, 25 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 631f5a8b..bf217679 100644 --- a/README.md +++ b/README.md @@ -156,6 +156,7 @@ Flashcard fields can be configured with the following steps: `{cloze-prefix}` | Text for the containing `{sentence}` from the start up to the value of `{cloze-body}`. `{cloze-suffix}` | Text for the containing `{sentence}` from the value of `{cloze-body}` to the end. `{dictionary}` | Name of the dictionary from which the card is being created (unavailable in *grouped* mode). + `{document-title}` | Title of the web page that the term appeared in. `{expression}` | Term expressed as Kanji (will be displayed in Kana if Kanji is not available). `{furigana}` | Term expressed as Kanji with Furigana displayed above it (e.g. 日本語にほんご). `{furigana-plain}` | Term expressed as Kanji with Furigana displayed next to it in brackets (e.g. 日本語[にほんご]). @@ -175,6 +176,7 @@ Flashcard fields can be configured with the following steps: `{cloze-prefix}` | Text for the containing `{sentence}` from the start up to the value of `{cloze-body}`. `{cloze-suffix}` | Text for the containing `{sentence}` from the value of `{cloze-body}` to the end. `{dictionary}` | Name of the dictionary from which the card is being created. + `{document-title}` | Title of the web page that the Kanji appeared in. `{glossary}` | List of definitions for the Kanji. `{kunyomi}` | Kunyomi (Japanese reading) for the Kanji expressed as Katakana. `{onyomi}` | Onyomi (Chinese reading) for the Kanji expressed as Hiragana. diff --git a/ext/bg/data/default-anki-field-templates.handlebars b/ext/bg/data/default-anki-field-templates.handlebars index 0442f7c5..6061851f 100644 --- a/ext/bg/data/default-anki-field-templates.handlebars +++ b/ext/bg/data/default-anki-field-templates.handlebars @@ -158,4 +158,8 @@ {{/inline}} +{{#*inline "document-title"}} + {{~context.document.title~}} +{{/inline}} + {{~> (lookup . "marker") ~}} \ No newline at end of file diff --git a/ext/bg/js/options.js b/ext/bg/js/options.js index 5c68c403..abb054d4 100644 --- a/ext/bg/js/options.js +++ b/ext/bg/js/options.js @@ -91,6 +91,15 @@ const profileOptionsVersionUpdates = [ if (utilStringHashCode(options.anki.fieldTemplates) === 1444379824) { options.anki.fieldTemplates = null; } + }, + (options) => { + // Version 13 changes: + // Default anki field tempaltes updated to include {document-title}. + let fieldTemplates = options.anki.fieldTemplates; + if (typeof fieldTemplates === 'string') { + fieldTemplates += '\n\n{{#*inline "document-title"}}\n {{~context.document.title~}}\n{{/inline}}'; + options.anki.fieldTemplates = fieldTemplates; + } } ]; diff --git a/ext/bg/js/settings/anki-templates.js b/ext/bg/js/settings/anki-templates.js index 88bca024..e3852eb4 100644 --- a/ext/bg/js/settings/anki-templates.js +++ b/ext/bg/js/settings/anki-templates.js @@ -99,7 +99,11 @@ async function ankiTemplatesValidate(infoNode, field, mode, showSuccessResult, i const definition = await ankiTemplatesValidateGetDefinition(text, optionsContext); if (definition !== null) { const options = await apiOptionsGet(optionsContext); - const context = {}; + const context = { + document: { + title: document.title + } + }; let templates = options.anki.fieldTemplates; if (typeof templates !== 'string') { templates = await apiGetDefaultAnkiFieldTemplates(); } const ankiNoteBuilder = new AnkiNoteBuilder({renderTemplate: apiTemplateRender}); diff --git a/ext/mixed/js/display.js b/ext/mixed/js/display.js index ecf92013..646d60e7 100644 --- a/ext/mixed/js/display.js +++ b/ext/mixed/js/display.js @@ -935,7 +935,11 @@ class Display { } _getNoteContext() { - return {}; + return { + document: { + title: document.title + } + }; } async _getAudioUri(definition, source) { From 1d7c86ded0a3ca559342dc394696cdc2504d28c4 Mon Sep 17 00:00:00 2001 From: toasted-nutbread Date: Fri, 27 Mar 2020 21:58:24 -0400 Subject: [PATCH 4/7] Add document-title tag to settings options --- ext/bg/js/settings/anki.js | 2 ++ 1 file changed, 2 insertions(+) diff --git a/ext/bg/js/settings/anki.js b/ext/bg/js/settings/anki.js index b706cd1b..f2e1ca76 100644 --- a/ext/bg/js/settings/anki.js +++ b/ext/bg/js/settings/anki.js @@ -243,6 +243,7 @@ function ankiGetFieldMarkers(type) { 'cloze-prefix', 'cloze-suffix', 'dictionary', + 'document-title', 'expression', 'furigana', 'furigana-plain', @@ -258,6 +259,7 @@ function ankiGetFieldMarkers(type) { return [ 'character', 'dictionary', + 'document-title', 'glossary', 'kunyomi', 'onyomi', From 199b926f239ddf64c95f23415851a11ba4bf7c2a Mon Sep 17 00:00:00 2001 From: toasted-nutbread Date: Fri, 27 Mar 2020 22:11:24 -0400 Subject: [PATCH 5/7] Add overridable getDocumentTitle --- ext/mixed/js/display.js | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/ext/mixed/js/display.js b/ext/mixed/js/display.js index 646d60e7..64c604e8 100644 --- a/ext/mixed/js/display.js +++ b/ext/mixed/js/display.js @@ -908,12 +908,17 @@ class Display { async getDefinitionsAddable(definitions, modes) { try { - return await apiDefinitionsAddable(definitions, modes, this._getNoteContext(), this.getOptionsContext()); + const context = await this._getNoteContext(); + return await apiDefinitionsAddable(definitions, modes, context, this.getOptionsContext()); } catch (e) { return []; } } + async getDocumentTitle() { + return document.title; + } + static indexOf(nodeList, node) { for (let i = 0, ii = nodeList.length; i < ii; ++i) { if (nodeList[i] === node) { @@ -934,10 +939,11 @@ class Display { return (typeof key === 'string' ? (key.length === 1 ? key.toUpperCase() : key) : ''); } - _getNoteContext() { + async _getNoteContext() { + const documentTitle = await this.getDocumentTitle(); return { document: { - title: document.title + title: documentTitle } }; } From 696897f6fa431c0c24332c5dd2a2c12a07923c0e Mon Sep 17 00:00:00 2001 From: toasted-nutbread Date: Mon, 6 Apr 2020 18:55:36 -0400 Subject: [PATCH 6/7] Add support for getting the document title --- ext/fg/js/float.js | 27 +++++++++++++++++++++++++++ ext/fg/js/frontend.js | 11 ++++++++++- 2 files changed, 37 insertions(+), 1 deletion(-) diff --git a/ext/fg/js/float.js b/ext/fg/js/float.js index 9b720ebe..01055ca6 100644 --- a/ext/fg/js/float.js +++ b/ext/fg/js/float.js @@ -162,6 +162,33 @@ class DisplayFloat extends Display { setContentScale(scale) { document.body.style.fontSize = `${scale}em`; } + + async getDocumentTitle() { + try { + const uniqueId = yomichan.generateId(16); + + const promise = yomichan.getTemporaryListenerResult( + chrome.runtime.onMessage, + ({action, params}, {resolve}) => { + if ( + action === 'documentInformationBroadcast' && + isObject(params) && + params.uniqueId === uniqueId && + params.frameId === 0 + ) { + resolve(params); + } + }, + 2000 + ); + apiForward('requestDocumentInformationBroadcast', {uniqueId}); + + const {title} = await promise; + return title; + } catch (e) { + return ''; + } + } } DisplayFloat.instance = new DisplayFloat(); diff --git a/ext/fg/js/frontend.js b/ext/fg/js/frontend.js index 4e9d474c..31843212 100644 --- a/ext/fg/js/frontend.js +++ b/ext/fg/js/frontend.js @@ -54,7 +54,8 @@ class Frontend extends TextScanner { this._runtimeMessageHandlers = new Map([ ['popupSetVisibleOverride', ({visible}) => { this.popup.setVisibleOverride(visible); }], - ['rootPopupRequestInformationBroadcast', () => { this._broadcastRootPopupInformation(); }] + ['rootPopupRequestInformationBroadcast', () => { this._broadcastRootPopupInformation(); }], + ['requestDocumentInformationBroadcast', ({uniqueId}) => { this._broadcastDocumentInformation(uniqueId); }] ]); } @@ -264,6 +265,14 @@ class Frontend extends TextScanner { } } + _broadcastDocumentInformation(uniqueId) { + apiForward('documentInformationBroadcast', { + uniqueId, + frameId: this.popup.frameId, + title: document.title + }); + } + async _updatePopupPosition() { const textSource = this.getCurrentTextSource(); if (textSource !== null && await this.popup.isVisible()) { From 29cf8d2f79f23b7723d508085ca242396bbbd5c9 Mon Sep 17 00:00:00 2001 From: toasted-nutbread Date: Mon, 6 Apr 2020 18:55:45 -0400 Subject: [PATCH 7/7] Fix not awaiting this._getNoteContext --- ext/mixed/js/display.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/ext/mixed/js/display.js b/ext/mixed/js/display.js index 64c604e8..2f456c3e 100644 --- a/ext/mixed/js/display.js +++ b/ext/mixed/js/display.js @@ -760,7 +760,8 @@ class Display { } } - const noteId = await apiDefinitionAdd(definition, mode, this._getNoteContext(), details, this.getOptionsContext()); + const context = await this._getNoteContext(); + const noteId = await apiDefinitionAdd(definition, mode, context, details, this.getOptionsContext()); if (noteId) { const index = this.definitions.indexOf(definition); const adderButton = this.adderButtonFind(index, mode);