Merge pull request #380 from toasted-nutbread/anki-templates-file

Load default Anki field templates from a file
This commit is contained in:
toasted-nutbread 2020-03-01 14:41:48 -05:00 committed by GitHub
commit a4b0a556d4
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 191 additions and 195 deletions

View File

@ -0,0 +1,161 @@
{{#*inline "glossary-single"}}
{{~#unless brief~}}
{{~#if definitionTags~}}<i>({{#each definitionTags}}{{name}}{{#unless @last}}, {{/unless}}{{/each}})</i> {{/if~}}
{{~#if only~}}({{#each only}}{{{.}}}{{#unless @last}}, {{/unless}}{{/each}} only) {{/if~}}
{{~/unless~}}
{{~#if glossary.[1]~}}
{{~#if compactGlossaries~}}
{{#each glossary}}{{#multiLine}}{{.}}{{/multiLine}}{{#unless @last}} | {{/unless}}{{/each}}
{{~else~}}
<ul>{{#each glossary}}<li>{{#multiLine}}{{.}}{{/multiLine}}</li>{{/each}}</ul>
{{~/if~}}
{{~else~}}
{{~#multiLine}}{{glossary.[0]}}{{/multiLine~}}
{{~/if~}}
{{/inline}}
{{#*inline "audio"}}{{/inline}}
{{#*inline "character"}}
{{~definition.character~}}
{{/inline}}
{{#*inline "dictionary"}}
{{~definition.dictionary~}}
{{/inline}}
{{#*inline "expression"}}
{{~#if merge~}}
{{~#if modeTermKana~}}
{{~#each definition.reading~}}
{{{.}}}
{{~#unless @last}}{{/unless~}}
{{~else~}}
{{~#each definition.expression~}}
{{{.}}}
{{~#unless @last}}{{/unless~}}
{{~/each~}}
{{~/each~}}
{{~else~}}
{{~#each definition.expression~}}
{{{.}}}
{{~#unless @last}}{{/unless~}}
{{~/each~}}
{{~/if~}}
{{~else~}}
{{~#if modeTermKana~}}
{{~#if definition.reading~}}
{{definition.reading}}
{{~else~}}
{{definition.expression}}
{{~/if~}}
{{~else~}}
{{definition.expression}}
{{~/if~}}
{{~/if~}}
{{/inline}}
{{#*inline "furigana"}}
{{~#if merge~}}
{{~#each definition.expressions~}}
<span class="expression-{{termFrequency}}">{{~#furigana}}{{{.}}}{{/furigana~}}</span>
{{~#unless @last}}{{/unless~}}
{{~/each~}}
{{~else~}}
{{#furigana}}{{{definition}}}{{/furigana}}
{{~/if~}}
{{/inline}}
{{#*inline "furigana-plain"}}
{{~#if merge~}}
{{~#each definition.expressions~}}
<span class="expression-{{termFrequency}}">{{~#furiganaPlain}}{{{.}}}{{/furiganaPlain~}}</span>
{{~#unless @last}}{{/unless~}}
{{~/each~}}
{{~else~}}
{{#furiganaPlain}}{{{definition}}}{{/furiganaPlain}}
{{~/if~}}
{{/inline}}
{{#*inline "glossary"}}
<div style="text-align: left;">
{{~#if modeKanji~}}
{{~#if definition.glossary.[1]~}}
<ol>{{#each definition.glossary}}<li>{{.}}</li>{{/each}}</ol>
{{~else~}}
{{definition.glossary.[0]}}
{{~/if~}}
{{~else~}}
{{~#if group~}}
{{~#if definition.definitions.[1]~}}
<ol>{{#each definition.definitions}}<li>{{> glossary-single brief=../brief compactGlossaries=../compactGlossaries}}</li>{{/each}}</ol>
{{~else~}}
{{~> glossary-single definition.definitions.[0] brief=brief compactGlossaries=compactGlossaries~}}
{{~/if~}}
{{~else if merge~}}
{{~#if definition.definitions.[1]~}}
<ol>{{#each definition.definitions}}<li>{{> glossary-single brief=../brief compactGlossaries=../compactGlossaries}}</li>{{/each}}</ol>
{{~else~}}
{{~> glossary-single definition.definitions.[0] brief=brief compactGlossaries=compactGlossaries~}}
{{~/if~}}
{{~else~}}
{{~> glossary-single definition brief=brief compactGlossaries=compactGlossaries~}}
{{~/if~}}
{{~/if~}}
</div>
{{/inline}}
{{#*inline "glossary-brief"}}
{{~> glossary brief=true ~}}
{{/inline}}
{{#*inline "kunyomi"}}
{{~#each definition.kunyomi}}{{.}}{{#unless @last}}, {{/unless}}{{/each~}}
{{/inline}}
{{#*inline "onyomi"}}
{{~#each definition.onyomi}}{{.}}{{#unless @last}}, {{/unless}}{{/each~}}
{{/inline}}
{{#*inline "reading"}}
{{~#unless modeTermKana~}}
{{~#if merge~}}
{{~#each definition.reading~}}
{{{.}}}
{{~#unless @last}}{{/unless~}}
{{~/each~}}
{{~else~}}
{{~definition.reading~}}
{{~/if~}}
{{~/unless~}}
{{/inline}}
{{#*inline "sentence"}}
{{~#if definition.cloze}}{{definition.cloze.sentence}}{{/if~}}
{{/inline}}
{{#*inline "cloze-prefix"}}
{{~#if definition.cloze}}{{definition.cloze.prefix}}{{/if~}}
{{/inline}}
{{#*inline "cloze-body"}}
{{~#if definition.cloze}}{{definition.cloze.body}}{{/if~}}
{{/inline}}
{{#*inline "cloze-suffix"}}
{{~#if definition.cloze}}{{definition.cloze.suffix}}{{/if~}}
{{/inline}}
{{#*inline "tags"}}
{{~#each definition.definitionTags}}{{name}}{{#unless @last}}, {{/unless}}{{/each~}}
{{/inline}}
{{#*inline "url"}}
<a href="{{definition.url}}">{{definition.url}}</a>
{{/inline}}
{{#*inline "screenshot"}}
<img src="{{definition.screenshotFileName}}" />
{{/inline}}
{{~> (lookup . "marker") ~}}

View File

@ -17,7 +17,7 @@
*/ */
/*global optionsSave, utilIsolate /*global optionsSave, utilIsolate
conditionsTestValue, profileConditionsDescriptor, profileOptionsGetDefaultFieldTemplates conditionsTestValue, profileConditionsDescriptor
handlebarsRenderDynamic handlebarsRenderDynamic
requestText, requestJson, optionsLoad requestText, requestJson, optionsLoad
dictConfigured, dictTermsSort, dictEnabledSet, dictNoteFormat dictConfigured, dictTermsSort, dictEnabledSet, dictNoteFormat
@ -33,6 +33,7 @@ class Backend {
this.clipboardMonitor = new ClipboardMonitor(); this.clipboardMonitor = new ClipboardMonitor();
this.options = null; this.options = null;
this.optionsSchema = null; this.optionsSchema = null;
this.defaultAnkiFieldTemplates = null;
this.optionsContext = { this.optionsContext = {
depth: 0, depth: 0,
url: window.location.href url: window.location.href
@ -74,7 +75,8 @@ class Backend {
['getDisplayTemplatesHtml', this._onApiGetDisplayTemplatesHtml.bind(this)], ['getDisplayTemplatesHtml', this._onApiGetDisplayTemplatesHtml.bind(this)],
['getQueryParserTemplatesHtml', this._onApiGetQueryParserTemplatesHtml.bind(this)], ['getQueryParserTemplatesHtml', this._onApiGetQueryParserTemplatesHtml.bind(this)],
['getZoom', this._onApiGetZoom.bind(this)], ['getZoom', this._onApiGetZoom.bind(this)],
['getMessageToken', this._onApiGetMessageToken.bind(this)] ['getMessageToken', this._onApiGetMessageToken.bind(this)],
['getDefaultAnkiFieldTemplates', this._onApiGetDefaultAnkiFieldTemplates.bind(this)]
]); ]);
this._commandHandlers = new Map([ this._commandHandlers = new Map([
@ -89,6 +91,7 @@ class Backend {
await this.translator.prepare(); await this.translator.prepare();
this.optionsSchema = await requestJson(chrome.runtime.getURL('/bg/data/options-schema.json'), 'GET'); this.optionsSchema = await requestJson(chrome.runtime.getURL('/bg/data/options-schema.json'), 'GET');
this.defaultAnkiFieldTemplates = await requestText(chrome.runtime.getURL('/bg/data/default-anki-field-templates.handlebars'), 'GET');
this.options = await optionsLoad(); this.options = await optionsLoad();
try { try {
this.options = JsonSchema.getValidValueOrDefault(this.optionsSchema, this.options); this.options = JsonSchema.getValidValueOrDefault(this.optionsSchema, this.options);
@ -423,7 +426,7 @@ class Backend {
async _onApiDefinitionAdd({definition, mode, context, optionsContext}) { async _onApiDefinitionAdd({definition, mode, context, optionsContext}) {
const options = await this.getOptions(optionsContext); const options = await this.getOptions(optionsContext);
const templates = Backend._getTemplates(options); const templates = this.defaultAnkiFieldTemplates;
if (mode !== 'kanji') { if (mode !== 'kanji') {
await audioInject( await audioInject(
@ -448,7 +451,7 @@ class Backend {
async _onApiDefinitionsAddable({definitions, modes, optionsContext}) { async _onApiDefinitionsAddable({definitions, modes, optionsContext}) {
const options = await this.getOptions(optionsContext); const options = await this.getOptions(optionsContext);
const templates = Backend._getTemplates(options); const templates = this.defaultAnkiFieldTemplates;
const states = []; const states = [];
try { try {
@ -656,6 +659,10 @@ class Backend {
return this.messageToken; return this.messageToken;
} }
async _onApiGetDefaultAnkiFieldTemplates() {
return this.defaultAnkiFieldTemplates;
}
// Command handlers // Command handlers
async _onCommandSearch(params) { async _onCommandSearch(params) {
@ -896,11 +903,6 @@ class Backend {
return 'chrome'; return 'chrome';
} }
} }
static _getTemplates(options) {
const templates = options.anki.fieldTemplates;
return typeof templates === 'string' ? templates : profileOptionsGetDefaultFieldTemplates();
}
} }
window.yomichanBackend = new Backend(); window.yomichanBackend = new Backend();

View File

@ -58,22 +58,17 @@ const profileOptionsVersionUpdates = [
options.scanning.modifier = options.scanning.requireShift ? 'shift' : 'none'; options.scanning.modifier = options.scanning.requireShift ? 'shift' : 'none';
}, },
(options) => { (options) => {
const fieldTemplatesDefault = profileOptionsGetDefaultFieldTemplates();
options.general.resultOutputMode = options.general.groupResults ? 'group' : 'split'; options.general.resultOutputMode = options.general.groupResults ? 'group' : 'split';
options.anki.fieldTemplates = ( options.anki.fieldTemplates = null;
(utilStringHashCode(options.anki.fieldTemplates) !== -805327496) ?
`{{#if merge}}${fieldTemplatesDefault}{{else}}${options.anki.fieldTemplates}{{/if}}` :
fieldTemplatesDefault
);
}, },
(options) => { (options) => {
if (utilStringHashCode(options.anki.fieldTemplates) === 1285806040) { if (utilStringHashCode(options.anki.fieldTemplates) === 1285806040) {
options.anki.fieldTemplates = profileOptionsGetDefaultFieldTemplates(); options.anki.fieldTemplates = null;
} }
}, },
(options) => { (options) => {
if (utilStringHashCode(options.anki.fieldTemplates) === -250091611) { if (utilStringHashCode(options.anki.fieldTemplates) === -250091611) {
options.anki.fieldTemplates = profileOptionsGetDefaultFieldTemplates(); options.anki.fieldTemplates = null;
} }
}, },
(options) => { (options) => {
@ -97,172 +92,6 @@ const profileOptionsVersionUpdates = [
} }
]; ];
function profileOptionsGetDefaultFieldTemplates() {
return `
{{#*inline "glossary-single"}}
{{~#unless brief~}}
{{~#if definitionTags~}}<i>({{#each definitionTags}}{{name}}{{#unless @last}}, {{/unless}}{{/each}})</i> {{/if~}}
{{~#if only~}}({{#each only}}{{{.}}}{{#unless @last}}, {{/unless}}{{/each}} only) {{/if~}}
{{~/unless~}}
{{~#if glossary.[1]~}}
{{~#if compactGlossaries~}}
{{#each glossary}}{{#multiLine}}{{.}}{{/multiLine}}{{#unless @last}} | {{/unless}}{{/each}}
{{~else~}}
<ul>{{#each glossary}}<li>{{#multiLine}}{{.}}{{/multiLine}}</li>{{/each}}</ul>
{{~/if~}}
{{~else~}}
{{~#multiLine}}{{glossary.[0]}}{{/multiLine~}}
{{~/if~}}
{{/inline}}
{{#*inline "audio"}}{{/inline}}
{{#*inline "character"}}
{{~definition.character~}}
{{/inline}}
{{#*inline "dictionary"}}
{{~definition.dictionary~}}
{{/inline}}
{{#*inline "expression"}}
{{~#if merge~}}
{{~#if modeTermKana~}}
{{~#each definition.reading~}}
{{{.}}}
{{~#unless @last}}{{/unless~}}
{{~else~}}
{{~#each definition.expression~}}
{{{.}}}
{{~#unless @last}}{{/unless~}}
{{~/each~}}
{{~/each~}}
{{~else~}}
{{~#each definition.expression~}}
{{{.}}}
{{~#unless @last}}{{/unless~}}
{{~/each~}}
{{~/if~}}
{{~else~}}
{{~#if modeTermKana~}}
{{~#if definition.reading~}}
{{definition.reading}}
{{~else~}}
{{definition.expression}}
{{~/if~}}
{{~else~}}
{{definition.expression}}
{{~/if~}}
{{~/if~}}
{{/inline}}
{{#*inline "furigana"}}
{{~#if merge~}}
{{~#each definition.expressions~}}
<span class="expression-{{termFrequency}}">{{~#furigana}}{{{.}}}{{/furigana~}}</span>
{{~#unless @last}}{{/unless~}}
{{~/each~}}
{{~else~}}
{{#furigana}}{{{definition}}}{{/furigana}}
{{~/if~}}
{{/inline}}
{{#*inline "furigana-plain"}}
{{~#if merge~}}
{{~#each definition.expressions~}}
<span class="expression-{{termFrequency}}">{{~#furiganaPlain}}{{{.}}}{{/furiganaPlain~}}</span>
{{~#unless @last}}{{/unless~}}
{{~/each~}}
{{~else~}}
{{#furiganaPlain}}{{{definition}}}{{/furiganaPlain}}
{{~/if~}}
{{/inline}}
{{#*inline "glossary"}}
<div style="text-align: left;">
{{~#if modeKanji~}}
{{~#if definition.glossary.[1]~}}
<ol>{{#each definition.glossary}}<li>{{.}}</li>{{/each}}</ol>
{{~else~}}
{{definition.glossary.[0]}}
{{~/if~}}
{{~else~}}
{{~#if group~}}
{{~#if definition.definitions.[1]~}}
<ol>{{#each definition.definitions}}<li>{{> glossary-single brief=../brief compactGlossaries=../compactGlossaries}}</li>{{/each}}</ol>
{{~else~}}
{{~> glossary-single definition.definitions.[0] brief=brief compactGlossaries=compactGlossaries~}}
{{~/if~}}
{{~else if merge~}}
{{~#if definition.definitions.[1]~}}
<ol>{{#each definition.definitions}}<li>{{> glossary-single brief=../brief compactGlossaries=../compactGlossaries}}</li>{{/each}}</ol>
{{~else~}}
{{~> glossary-single definition.definitions.[0] brief=brief compactGlossaries=compactGlossaries~}}
{{~/if~}}
{{~else~}}
{{~> glossary-single definition brief=brief compactGlossaries=compactGlossaries~}}
{{~/if~}}
{{~/if~}}
</div>
{{/inline}}
{{#*inline "glossary-brief"}}
{{~> glossary brief=true ~}}
{{/inline}}
{{#*inline "kunyomi"}}
{{~#each definition.kunyomi}}{{.}}{{#unless @last}}, {{/unless}}{{/each~}}
{{/inline}}
{{#*inline "onyomi"}}
{{~#each definition.onyomi}}{{.}}{{#unless @last}}, {{/unless}}{{/each~}}
{{/inline}}
{{#*inline "reading"}}
{{~#unless modeTermKana~}}
{{~#if merge~}}
{{~#each definition.reading~}}
{{{.}}}
{{~#unless @last}}{{/unless~}}
{{~/each~}}
{{~else~}}
{{~definition.reading~}}
{{~/if~}}
{{~/unless~}}
{{/inline}}
{{#*inline "sentence"}}
{{~#if definition.cloze}}{{definition.cloze.sentence}}{{/if~}}
{{/inline}}
{{#*inline "cloze-prefix"}}
{{~#if definition.cloze}}{{definition.cloze.prefix}}{{/if~}}
{{/inline}}
{{#*inline "cloze-body"}}
{{~#if definition.cloze}}{{definition.cloze.body}}{{/if~}}
{{/inline}}
{{#*inline "cloze-suffix"}}
{{~#if definition.cloze}}{{definition.cloze.suffix}}{{/if~}}
{{/inline}}
{{#*inline "tags"}}
{{~#each definition.definitionTags}}{{name}}{{#unless @last}}, {{/unless}}{{/each~}}
{{/inline}}
{{#*inline "url"}}
<a href="{{definition.url}}">{{definition.url}}</a>
{{/inline}}
{{#*inline "screenshot"}}
<img src="{{definition.screenshotFileName}}" />
{{/inline}}
{{~> (lookup . "marker") ~}}
`.trim();
}
function profileOptionsCreateDefaults() { function profileOptionsCreateDefaults() {
return { return {
general: { general: {

View File

@ -17,21 +17,23 @@
*/ */
/*global getOptionsContext, getOptionsMutable, settingsSaveOptions /*global getOptionsContext, getOptionsMutable, settingsSaveOptions
profileOptionsGetDefaultFieldTemplates, ankiGetFieldMarkers, ankiGetFieldMarkersHtml, dictFieldFormat ankiGetFieldMarkers, ankiGetFieldMarkersHtml, dictFieldFormat
apiOptionsGet, apiTermsFind*/ apiOptionsGet, apiTermsFind, apiGetDefaultAnkiFieldTemplates*/
function onAnkiFieldTemplatesReset(e) { function onAnkiFieldTemplatesReset(e) {
e.preventDefault(); e.preventDefault();
$('#field-template-reset-modal').modal('show'); $('#field-template-reset-modal').modal('show');
} }
function onAnkiFieldTemplatesResetConfirm(e) { async function onAnkiFieldTemplatesResetConfirm(e) {
e.preventDefault(); e.preventDefault();
$('#field-template-reset-modal').modal('hide'); $('#field-template-reset-modal').modal('hide');
const value = await apiGetDefaultAnkiFieldTemplates();
const element = document.querySelector('#field-templates'); const element = document.querySelector('#field-templates');
element.value = profileOptionsGetDefaultFieldTemplates(); element.value = value;
element.dispatchEvent(new Event('change')); element.dispatchEvent(new Event('change'));
} }
@ -57,7 +59,7 @@ async function ankiTemplatesUpdateValue() {
const optionsContext = getOptionsContext(); const optionsContext = getOptionsContext();
const options = await apiOptionsGet(optionsContext); const options = await apiOptionsGet(optionsContext);
let templates = options.anki.fieldTemplates; let templates = options.anki.fieldTemplates;
if (typeof templates !== 'string') { templates = profileOptionsGetDefaultFieldTemplates(); } if (typeof templates !== 'string') { templates = await apiGetDefaultAnkiFieldTemplates(); }
$('#field-templates').val(templates); $('#field-templates').val(templates);
onAnkiTemplatesValidateCompile(); onAnkiTemplatesValidateCompile();
@ -89,7 +91,7 @@ async function ankiTemplatesValidate(infoNode, field, mode, showSuccessResult, i
if (definition !== null) { if (definition !== null) {
const options = await apiOptionsGet(optionsContext); const options = await apiOptionsGet(optionsContext);
let templates = options.anki.fieldTemplates; let templates = options.anki.fieldTemplates;
if (typeof templates !== 'string') { templates = profileOptionsGetDefaultFieldTemplates(); } if (typeof templates !== 'string') { templates = await apiGetDefaultAnkiFieldTemplates(); }
result = await dictFieldFormat(field, definition, mode, options, templates, exceptions); result = await dictFieldFormat(field, definition, mode, options, templates, exceptions);
} }
} catch (e) { } catch (e) {
@ -109,7 +111,7 @@ async function ankiTemplatesValidate(infoNode, field, mode, showSuccessResult, i
async function onAnkiFieldTemplatesChanged(e) { async function onAnkiFieldTemplatesChanged(e) {
// Get value // Get value
let templates = e.currentTarget.value; let templates = e.currentTarget.value;
if (templates === profileOptionsGetDefaultFieldTemplates()) { if (templates === await apiGetDefaultAnkiFieldTemplates()) {
// Default // Default
templates = null; templates = null;
} }

View File

@ -16,10 +16,9 @@
* 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 apiOptionsGetFull, apiGetEnvironmentInfo /*global apiOptionsGetFull, apiGetEnvironmentInfo, apiGetDefaultAnkiFieldTemplates
utilBackend, utilIsolate, utilBackgroundIsolate, utilReadFileArrayBuffer utilBackend, utilIsolate, utilBackgroundIsolate, utilReadFileArrayBuffer
optionsGetDefault, optionsUpdateVersion optionsGetDefault, optionsUpdateVersion*/
profileOptionsGetDefaultFieldTemplates*/
// Exporting // Exporting
@ -47,8 +46,7 @@ function _getSettingsExportDateString(date, dateSeparator, dateTimeSeparator, ti
async function _getSettingsExportData(date) { async function _getSettingsExportData(date) {
const optionsFull = await apiOptionsGetFull(); const optionsFull = await apiOptionsGetFull();
const environment = await apiGetEnvironmentInfo(); const environment = await apiGetEnvironmentInfo();
const fieldTemplatesDefault = await apiGetDefaultAnkiFieldTemplates();
const fieldTemplatesDefault = profileOptionsGetDefaultFieldTemplates();
// Format options // Format options
for (const {options} of optionsFull.profiles) { for (const {options} of optionsFull.profiles) {

View File

@ -117,6 +117,10 @@ function apiGetMessageToken() {
return _apiInvoke('getMessageToken'); return _apiInvoke('getMessageToken');
} }
function apiGetDefaultAnkiFieldTemplates() {
return _apiInvoke('getDefaultAnkiFieldTemplates');
}
function _apiInvoke(action, params={}) { function _apiInvoke(action, params={}) {
const data = {action, params}; const data = {action, params};
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {