summaryrefslogtreecommitdiff
path: root/ext
diff options
context:
space:
mode:
authorAlex Yatskov <alex@foosoft.net>2017-09-11 16:56:27 -0700
committerAlex Yatskov <alex@foosoft.net>2017-09-11 16:56:27 -0700
commit3a1aad07d61411f634e86f905babd6fbbac2eae1 (patch)
treef343fc427c0c791823a39a482dc3d1cd35d34253 /ext
parent65b679caeb7ae7261ea6f2ba76d1b14ff1d68c5c (diff)
parent2eb85cb835a4aece7839eba25c0030e9eb186f85 (diff)
Merge branch 'master' into firefox-amo
Diffstat (limited to 'ext')
-rw-r--r--ext/bg/js/api.js14
-rw-r--r--ext/bg/js/backend.js4
-rw-r--r--ext/bg/js/dictionary.js10
-rw-r--r--ext/bg/js/handlebars.js19
-rw-r--r--ext/bg/js/options.js113
-rw-r--r--ext/bg/js/settings.js20
-rw-r--r--ext/bg/js/templates.js307
-rw-r--r--ext/bg/settings.html55
-rw-r--r--ext/fg/js/api.js4
-rw-r--r--ext/manifest.json3
10 files changed, 198 insertions, 351 deletions
diff --git a/ext/bg/js/api.js b/ext/bg/js/api.js
index 96147d95..5c1aebb6 100644
--- a/ext/bg/js/api.js
+++ b/ext/bg/js/api.js
@@ -62,7 +62,8 @@ async function apiDefinitionAdd(definition, mode) {
);
}
- return utilBackend().anki.addNote(dictNoteFormat(definition, mode, options));
+ const note = await dictNoteFormat(definition, mode, options);
+ return utilBackend().anki.addNote(note);
}
async function apiDefinitionsAddable(definitions, modes) {
@@ -72,7 +73,8 @@ async function apiDefinitionsAddable(definitions, modes) {
const notes = [];
for (const definition of definitions) {
for (const mode of modes) {
- notes.push(dictNoteFormat(definition, mode, utilBackend().options));
+ const note = await dictNoteFormat(definition, mode, utilBackend().options);
+ notes.push(note);
}
}
@@ -96,8 +98,12 @@ async function apiNoteView(noteId) {
return utilBackend().anki.guiBrowse(`nid:${noteId}`);
}
-async function apiTemplateRender(template, data) {
- return handlebarsRender(template, data);
+async function apiTemplateRender(template, data, dynamic) {
+ if (dynamic) {
+ return handlebarsRenderDynamic(template, data);
+ } else {
+ return handlebarsRenderStatic(template, data);
+ }
}
async function apiCommandExec(command) {
diff --git a/ext/bg/js/backend.js b/ext/bg/js/backend.js
index 6b3acaa9..7d68ed84 100644
--- a/ext/bg/js/backend.js
+++ b/ext/bg/js/backend.js
@@ -104,8 +104,8 @@ class Backend {
forward(apiNoteView(noteId), callback);
},
- templateRender: ({template, data, callback}) => {
- forward(apiTemplateRender(template, data), callback);
+ templateRender: ({template, data, dynamic, callback}) => {
+ forward(apiTemplateRender(template, data, dynamic), callback);
},
commandExec: ({command, callback}) => {
diff --git a/ext/bg/js/dictionary.js b/ext/bg/js/dictionary.js
index 78240157..e749390f 100644
--- a/ext/bg/js/dictionary.js
+++ b/ext/bg/js/dictionary.js
@@ -192,7 +192,7 @@ function dictFieldSplit(field) {
return field.length === 0 ? [] : field.split(' ');
}
-function dictFieldFormat(field, definition, mode, options) {
+async function dictFieldFormat(field, definition, mode, options) {
const markers = [
'audio',
'character',
@@ -218,19 +218,19 @@ function dictFieldFormat(field, definition, mode, options) {
marker,
definition,
group: options.general.groupResults,
- html: options.anki.htmlCards,
modeTermKanji: mode === 'term-kanji',
modeTermKana: mode === 'term-kana',
modeKanji: mode === 'kanji'
};
- field = field.replace(`{${marker}}`, handlebarsRender('fields.html', data));
+ const html = await apiTemplateRender(options.anki.fieldTemplates, data, true);
+ field = field.replace(`{${marker}}`, html);
}
return field;
}
-function dictNoteFormat(definition, mode, options) {
+async function dictNoteFormat(definition, mode, options) {
const note = {fields: {}, tags: options.anki.tags};
let fields = [];
@@ -264,7 +264,7 @@ function dictNoteFormat(definition, mode, options) {
}
for (const name in fields) {
- note.fields[name] = dictFieldFormat(fields[name], definition, mode, options);
+ note.fields[name] = await dictFieldFormat(fields[name], definition, mode, options);
}
return note;
diff --git a/ext/bg/js/handlebars.js b/ext/bg/js/handlebars.js
index e0804986..66d5fa2b 100644
--- a/ext/bg/js/handlebars.js
+++ b/ext/bg/js/handlebars.js
@@ -75,7 +75,7 @@ function handlebarsMultiLine(options) {
return options.fn(this).split('\n').join('<br>');
}
-function handlebarsRender(template, data) {
+function handlebarsRegisterHelpers() {
if (Handlebars.partials !== Handlebars.templates) {
Handlebars.partials = Handlebars.templates;
Handlebars.registerHelper('dumpObject', handlebarsDumpObject);
@@ -84,6 +84,21 @@ function handlebarsRender(template, data) {
Handlebars.registerHelper('kanjiLinks', handlebarsKanjiLinks);
Handlebars.registerHelper('multiLine', handlebarsMultiLine);
}
+}
+
+function handlebarsRenderStatic(name, data) {
+ handlebarsRegisterHelpers();
+ return Handlebars.templates[name](data).trim();
+}
+
+function handlebarsRenderDynamic(template, data) {
+ handlebarsRegisterHelpers();
+
+ Handlebars.yomichan_cache = Handlebars.yomichan_cache || {};
+ let instance = Handlebars.yomichan_cache[template];
+ if (!instance) {
+ instance = Handlebars.yomichan_cache[template] = Handlebars.compile(template);
+ }
- return Handlebars.templates[template](data).trim();
+ return instance(data).trim();
}
diff --git a/ext/bg/js/options.js b/ext/bg/js/options.js
index ea52d337..dcad97d4 100644
--- a/ext/bg/js/options.js
+++ b/ext/bg/js/options.js
@@ -17,6 +17,115 @@
*/
+function optionsFieldTemplates() {
+ return `
+{{#*inline "glossary-single"}}
+ {{~#unless brief~}}
+ {{~#if tags~}}<i>({{#each tags}}{{name}}{{#unless @last}}, {{/unless}}{{/each}})</i> {{/if~}}
+ {{~/unless~}}
+ {{~#if glossary.[1]~}}
+ <ul>{{#each glossary}}<li>{{#multiLine}}{{.}}{{/multiLine}}</li>{{/each}}</ul>
+ {{~else~}}
+ {{~#multiLine}}{{glossary.[0]}}{{/multiLine~}}
+ {{~/if~}}
+{{/inline}}
+
+{{#*inline "audio"}}{{/inline}}
+
+{{#*inline "character"}}
+ {{~definition.character~}}
+{{/inline}}
+
+{{#*inline "dictionary"}}
+ {{~definition.dictionary~}}
+{{/inline}}
+
+{{#*inline "expression"}}
+ {{~#if modeTermKana~}}
+ {{~#if definition.reading~}}
+ {{definition.reading}}
+ {{~else~}}
+ {{definition.expression}}
+ {{~/if~}}
+ {{~else~}}
+ {{definition.expression}}
+ {{~/if~}}
+{{/inline}}
+
+{{#*inline "furigana"}}
+ {{#furigana}}{{{definition}}}{{/furigana}}
+{{/inline}}
+
+{{#*inline "furigana-plain"}}
+ {{#furiganaPlain}}{{{definition}}}{{/furiganaPlain}}
+{{/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}}</li>{{/each}}</ol>
+ {{~else~}}
+ {{~> glossary-single definition.definitions.[0] brief=brief~}}
+ {{~/if~}}
+ {{~else~}}
+ {{~> glossary-single definition brief=brief~}}
+ {{~/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}}{{definition.reading}}{{/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.tags}}{{name}}{{#unless @last}}, {{/unless}}{{/each~}}
+{{/inline}}
+
+{{#*inline "url"}}
+ <a href="{{definition.url}}">{{definition.url}}</a>
+{{/inline}}
+
+{{~> (lookup . "marker") ~}}
+`.trim();
+}
+
function optionsSetDefaults(options) {
const defaults = {
general: {
@@ -48,10 +157,10 @@ function optionsSetDefaults(options) {
enable: false,
server: 'http://127.0.0.1:8765',
tags: ['yomichan'],
- htmlCards: true,
sentenceExt: 200,
terms: {deck: '', model: '', fields: {}},
- kanji: {deck: '', model: '', fields: {}}
+ kanji: {deck: '', model: '', fields: {}},
+ fieldTemplates: optionsFieldTemplates()
}
};
diff --git a/ext/bg/js/settings.js b/ext/bg/js/settings.js
index c029b30b..55b469d0 100644
--- a/ext/bg/js/settings.js
+++ b/ext/bg/js/settings.js
@@ -41,9 +41,9 @@ async function formRead() {
optionsNew.anki.enable = $('#anki-enable').prop('checked');
optionsNew.anki.tags = $('#card-tags').val().split(/[,; ]+/);
- optionsNew.anki.htmlCards = $('#generate-html-cards').prop('checked');
optionsNew.anki.sentenceExt = parseInt($('#sentence-detection-extent').val(), 10);
optionsNew.anki.server = $('#interface-server').val();
+ optionsNew.anki.fieldTemplates = $('#field-templates').val();
if (optionsOld.anki.enable && !ankiErrorShown()) {
optionsNew.anki.terms.deck = $('#anki-terms-deck').val();
@@ -143,10 +143,11 @@ async function onReady() {
$('#anki-enable').prop('checked', options.anki.enable);
$('#card-tags').val(options.anki.tags.join(' '));
- $('#generate-html-cards').prop('checked', options.anki.htmlCards);
$('#sentence-detection-extent').val(options.anki.sentenceExt);
$('#interface-server').val(options.anki.server);
- $('input, select').not('.anki-model').change(utilAsync(onFormOptionsChanged));
+ $('#field-templates').val(options.anki.fieldTemplates);
+ $('#field-templates-reset').click(utilAsync(onAnkiFieldTemplatesReset));
+ $('input, select, textarea').not('.anki-model').change(utilAsync(onFormOptionsChanged));
$('.anki-model').change(utilAsync(onAnkiModelChanged));
try {
@@ -217,7 +218,7 @@ async function dictionaryGroupsPopulate(options) {
for (const dictRow of dictRowsSort(dictRows, options)) {
const dictOptions = options.dictionaries[dictRow.title] || {enabled: false, priority: 0};
- const dictHtml = handlebarsRender('dictionary.html', {
+ const dictHtml = await apiTemplateRender('dictionary.html', {
title: dictRow.title,
version: dictRow.version,
revision: dictRow.revision,
@@ -429,3 +430,14 @@ async function onAnkiModelChanged(e) {
ankiSpinnerShow(false);
}
}
+
+async function onAnkiFieldTemplatesReset(e) {
+ try {
+ e.preventDefault();
+ const options = await optionsLoad();
+ $('#field-templates').val(options.anki.fieldTemplates = optionsFieldTemplates());
+ await optionsSave(options);
+ } catch (e) {
+ ankiErrorShow(e);
+ }
+}
diff --git a/ext/bg/js/templates.js b/ext/bg/js/templates.js
index f18e70fb..1c059365 100644
--- a/ext/bg/js/templates.js
+++ b/ext/bg/js/templates.js
@@ -21,313 +21,6 @@ templates['dictionary.html'] = template({"1":function(container,depth0,helpers,p
+ alias4(((helper = (helper = helpers.title || (depth0 != null ? depth0.title : depth0)) != null ? helper : alias2),(typeof helper === alias3 ? helper.call(alias1,{"name":"title","hash":{},"data":data}) : helper)))
+ "\" class=\"form-control dict-priority\">\n </div>\n</div>\n";
},"useData":true});
-templates['fields.html'] = template({"1":function(container,depth0,helpers,partials,data) {
- var stack1;
-
- return ((stack1 = helpers["if"].call(depth0 != null ? depth0 : (container.nullContext || {}),(depth0 != null ? depth0.html : depth0),{"name":"if","hash":{},"fn":container.program(2, data, 0),"inverse":container.program(15, data, 0),"data":data})) != null ? stack1 : "");
-},"2":function(container,depth0,helpers,partials,data) {
- var stack1, alias1=depth0 != null ? depth0 : (container.nullContext || {});
-
- return ((stack1 = helpers.unless.call(alias1,(depth0 != null ? depth0.brief : depth0),{"name":"unless","hash":{},"fn":container.program(3, data, 0),"inverse":container.noop,"data":data})) != null ? stack1 : "")
- + ((stack1 = helpers["if"].call(alias1,((stack1 = (depth0 != null ? depth0.glossary : depth0)) != null ? stack1["1"] : stack1),{"name":"if","hash":{},"fn":container.program(8, data, 0),"inverse":container.program(12, data, 0),"data":data})) != null ? stack1 : "");
-},"3":function(container,depth0,helpers,partials,data) {
- var stack1;
-
- return ((stack1 = helpers["if"].call(depth0 != null ? depth0 : (container.nullContext || {}),(depth0 != null ? depth0.tags : depth0),{"name":"if","hash":{},"fn":container.program(4, data, 0),"inverse":container.noop,"data":data})) != null ? stack1 : "");
-},"4":function(container,depth0,helpers,partials,data) {
- var stack1;
-
- return "<i>("
- + ((stack1 = helpers.each.call(depth0 != null ? depth0 : (container.nullContext || {}),(depth0 != null ? depth0.tags : depth0),{"name":"each","hash":{},"fn":container.program(5, data, 0),"inverse":container.noop,"data":data})) != null ? stack1 : "")
- + ")</i> ";
-},"5":function(container,depth0,helpers,partials,data) {
- var stack1, helper, alias1=depth0 != null ? depth0 : (container.nullContext || {});
-
- return container.escapeExpression(((helper = (helper = helpers.name || (depth0 != null ? depth0.name : depth0)) != null ? helper : helpers.helperMissing),(typeof helper === "function" ? helper.call(alias1,{"name":"name","hash":{},"data":data}) : helper)))
- + ((stack1 = helpers.unless.call(alias1,(data && data.last),{"name":"unless","hash":{},"fn":container.program(6, data, 0),"inverse":container.noop,"data":data})) != null ? stack1 : "");
-},"6":function(container,depth0,helpers,partials,data) {
- return ", ";
-},"8":function(container,depth0,helpers,partials,data) {
- var stack1;
-
- return "<ul>"
- + ((stack1 = helpers.each.call(depth0 != null ? depth0 : (container.nullContext || {}),(depth0 != null ? depth0.glossary : depth0),{"name":"each","hash":{},"fn":container.program(9, data, 0),"inverse":container.noop,"data":data})) != null ? stack1 : "")
- + "</ul>";
-},"9":function(container,depth0,helpers,partials,data) {
- var stack1, helper, options, buffer =
- "<li>";
- stack1 = ((helper = (helper = helpers.multiLine || (depth0 != null ? depth0.multiLine : depth0)) != null ? helper : helpers.helperMissing),(options={"name":"multiLine","hash":{},"fn":container.program(10, data, 0),"inverse":container.noop,"data":data}),(typeof helper === "function" ? helper.call(depth0 != null ? depth0 : (container.nullContext || {}),options) : helper));
- if (!helpers.multiLine) { stack1 = helpers.blockHelperMissing.call(depth0,stack1,options)}
- if (stack1 != null) { buffer += stack1; }
- return buffer + "</li>";
-},"10":function(container,depth0,helpers,partials,data) {
- return container.escapeExpression(container.lambda(depth0, depth0));
-},"12":function(container,depth0,helpers,partials,data) {
- var stack1, helper, options, buffer = "";
-
- stack1 = ((helper = (helper = helpers.multiLine || (depth0 != null ? depth0.multiLine : depth0)) != null ? helper : helpers.helperMissing),(options={"name":"multiLine","hash":{},"fn":container.program(13, data, 0),"inverse":container.noop,"data":data}),(typeof helper === "function" ? helper.call(depth0 != null ? depth0 : (container.nullContext || {}),options) : helper));
- if (!helpers.multiLine) { stack1 = helpers.blockHelperMissing.call(depth0,stack1,options)}
- if (stack1 != null) { buffer += stack1; }
- return buffer;
-},"13":function(container,depth0,helpers,partials,data) {
- var stack1;
-
- return container.escapeExpression(container.lambda(((stack1 = (depth0 != null ? depth0.glossary : depth0)) != null ? stack1["0"] : stack1), depth0));
-},"15":function(container,depth0,helpers,partials,data) {
- var stack1, alias1=depth0 != null ? depth0 : (container.nullContext || {});
-
- return ((stack1 = helpers.unless.call(alias1,(depth0 != null ? depth0.brief : depth0),{"name":"unless","hash":{},"fn":container.program(16, data, 0),"inverse":container.noop,"data":data})) != null ? stack1 : "")
- + ((stack1 = helpers["if"].call(alias1,((stack1 = (depth0 != null ? depth0.glossary : depth0)) != null ? stack1["1"] : stack1),{"name":"if","hash":{},"fn":container.program(19, data, 0),"inverse":container.program(13, data, 0),"data":data})) != null ? stack1 : "");
-},"16":function(container,depth0,helpers,partials,data) {
- var stack1;
-
- return ((stack1 = helpers["if"].call(depth0 != null ? depth0 : (container.nullContext || {}),(depth0 != null ? depth0.tags : depth0),{"name":"if","hash":{},"fn":container.program(17, data, 0),"inverse":container.noop,"data":data})) != null ? stack1 : "");
-},"17":function(container,depth0,helpers,partials,data) {
- var stack1;
-
- return "("
- + ((stack1 = helpers.each.call(depth0 != null ? depth0 : (container.nullContext || {}),(depth0 != null ? depth0.tags : depth0),{"name":"each","hash":{},"fn":container.program(5, data, 0),"inverse":container.noop,"data":data})) != null ? stack1 : "")
- + ") ";
-},"19":function(container,depth0,helpers,partials,data) {
- var stack1;
-
- return ((stack1 = helpers.each.call(depth0 != null ? depth0 : (container.nullContext || {}),(depth0 != null ? depth0.glossary : depth0),{"name":"each","hash":{},"fn":container.program(20, data, 0),"inverse":container.noop,"data":data})) != null ? stack1 : "");
-},"20":function(container,depth0,helpers,partials,data) {
- var stack1;
-
- return container.escapeExpression(container.lambda(depth0, depth0))
- + ((stack1 = helpers.unless.call(depth0 != null ? depth0 : (container.nullContext || {}),(data && data.last),{"name":"unless","hash":{},"fn":container.program(6, data, 0),"inverse":container.noop,"data":data})) != null ? stack1 : "");
-},"22":function(container,depth0,helpers,partials,data) {
- return "";
-},"24":function(container,depth0,helpers,partials,data) {
- var stack1;
-
- return container.escapeExpression(container.lambda(((stack1 = (depth0 != null ? depth0.definition : depth0)) != null ? stack1.character : stack1), depth0));
-},"26":function(container,depth0,helpers,partials,data) {
- var stack1;
-
- return container.escapeExpression(container.lambda(((stack1 = (depth0 != null ? depth0.definition : depth0)) != null ? stack1.dictionary : stack1), depth0));
-},"28":function(container,depth0,helpers,partials,data) {
- var stack1;
-
- return ((stack1 = helpers["if"].call(depth0 != null ? depth0 : (container.nullContext || {}),(depth0 != null ? depth0.modeTermKana : depth0),{"name":"if","hash":{},"fn":container.program(29, data, 0),"inverse":container.program(32, data, 0),"data":data})) != null ? stack1 : "");
-},"29":function(container,depth0,helpers,partials,data) {
- var stack1;
-
- return ((stack1 = helpers["if"].call(depth0 != null ? depth0 : (container.nullContext || {}),((stack1 = (depth0 != null ? depth0.definition : depth0)) != null ? stack1.reading : stack1),{"name":"if","hash":{},"fn":container.program(30, data, 0),"inverse":container.program(32, data, 0),"data":data})) != null ? stack1 : "");
-},"30":function(container,depth0,helpers,partials,data) {
- var stack1;
-
- return container.escapeExpression(container.lambda(((stack1 = (depth0 != null ? depth0.definition : depth0)) != null ? stack1.reading : stack1), depth0));
-},"32":function(container,depth0,helpers,partials,data) {
- var stack1;
-
- return container.escapeExpression(container.lambda(((stack1 = (depth0 != null ? depth0.definition : depth0)) != null ? stack1.expression : stack1), depth0));
-},"34":function(container,depth0,helpers,partials,data) {
- var stack1;
-
- return ((stack1 = helpers["if"].call(depth0 != null ? depth0 : (container.nullContext || {}),(depth0 != null ? depth0.html : depth0),{"name":"if","hash":{},"fn":container.program(35, data, 0),"inverse":container.program(38, data, 0),"data":data})) != null ? stack1 : "");
-},"35":function(container,depth0,helpers,partials,data) {
- var stack1, helper, options, buffer = "";
-
- stack1 = ((helper = (helper = helpers.furigana || (depth0 != null ? depth0.furigana : depth0)) != null ? helper : helpers.helperMissing),(options={"name":"furigana","hash":{},"fn":container.program(36, data, 0),"inverse":container.noop,"data":data}),(typeof helper === "function" ? helper.call(depth0 != null ? depth0 : (container.nullContext || {}),options) : helper));
- if (!helpers.furigana) { stack1 = helpers.blockHelperMissing.call(depth0,stack1,options)}
- if (stack1 != null) { buffer += stack1; }
- return buffer;
-},"36":function(container,depth0,helpers,partials,data) {
- var stack1, helper;
-
- return ((stack1 = ((helper = (helper = helpers.definition || (depth0 != null ? depth0.definition : depth0)) != null ? helper : helpers.helperMissing),(typeof helper === "function" ? helper.call(depth0 != null ? depth0 : (container.nullContext || {}),{"name":"definition","hash":{},"data":data}) : helper))) != null ? stack1 : "");
-},"38":function(container,depth0,helpers,partials,data) {
- var stack1, helper, options, buffer = "";
-
- stack1 = ((helper = (helper = helpers.furiganaPlain || (depth0 != null ? depth0.furiganaPlain : depth0)) != null ? helper : helpers.helperMissing),(options={"name":"furiganaPlain","hash":{},"fn":container.program(36, data, 0),"inverse":container.noop,"data":data}),(typeof helper === "function" ? helper.call(depth0 != null ? depth0 : (container.nullContext || {}),options) : helper));
- if (!helpers.furiganaPlain) { stack1 = helpers.blockHelperMissing.call(depth0,stack1,options)}
- if (stack1 != null) { buffer += stack1; }
- return buffer;
-},"40":function(container,depth0,helpers,partials,data) {
- var stack1, helper, options, buffer =
- " ";
- stack1 = ((helper = (helper = helpers.furiganaPlain || (depth0 != null ? depth0.furiganaPlain : depth0)) != null ? helper : helpers.helperMissing),(options={"name":"furiganaPlain","hash":{},"fn":container.program(36, data, 0),"inverse":container.noop,"data":data}),(typeof helper === "function" ? helper.call(depth0 != null ? depth0 : (container.nullContext || {}),options) : helper));
- if (!helpers.furiganaPlain) { stack1 = helpers.blockHelperMissing.call(depth0,stack1,options)}
- if (stack1 != null) { buffer += stack1; }
- return buffer + "\n";
-},"42":function(container,depth0,helpers,partials,data,blockParams,depths) {
- var stack1, alias1=depth0 != null ? depth0 : (container.nullContext || {});
-
- return ((stack1 = helpers["if"].call(alias1,(depth0 != null ? depth0.html : depth0),{"name":"if","hash":{},"fn":container.program(43, data, 0, blockParams, depths),"inverse":container.noop,"data":data})) != null ? stack1 : "")
- + ((stack1 = helpers["if"].call(alias1,(depth0 != null ? depth0.modeKanji : depth0),{"name":"if","hash":{},"fn":container.program(45, data, 0, blockParams, depths),"inverse":container.program(54, data, 0, blockParams, depths),"data":data})) != null ? stack1 : "")
- + ((stack1 = helpers["if"].call(alias1,(depth0 != null ? depth0.html : depth0),{"name":"if","hash":{},"fn":container.program(67, data, 0, blockParams, depths),"inverse":container.noop,"data":data})) != null ? stack1 : "");
-},"43":function(container,depth0,helpers,partials,data) {
- return "<div style=\"text-align: left;\">";
-},"45":function(container,depth0,helpers,partials,data) {
- var stack1;
-
- return ((stack1 = helpers["if"].call(depth0 != null ? depth0 : (container.nullContext || {}),((stack1 = ((stack1 = (depth0 != null ? depth0.definition : depth0)) != null ? stack1.glossary : stack1)) != null ? stack1["1"] : stack1),{"name":"if","hash":{},"fn":container.program(46, data, 0),"inverse":container.program(52, data, 0),"data":data})) != null ? stack1 : "");
-},"46":function(container,depth0,helpers,partials,data) {
- var stack1;
-
- return ((stack1 = helpers["if"].call(depth0 != null ? depth0 : (container.nullContext || {}),(depth0 != null ? depth0.html : depth0),{"name":"if","hash":{},"fn":container.program(47, data, 0),"inverse":container.program(50, data, 0),"data":data})) != null ? stack1 : "");
-},"47":function(container,depth0,helpers,partials,data) {
- var stack1;
-
- return "<ol>"
- + ((stack1 = helpers.each.call(depth0 != null ? depth0 : (container.nullContext || {}),((stack1 = (depth0 != null ? depth0.definition : depth0)) != null ? stack1.glossary : stack1),{"name":"each","hash":{},"fn":container.program(48, data, 0),"inverse":container.noop,"data":data})) != null ? stack1 : "")
- + "</ol>";
-},"48":function(container,depth0,helpers,partials,data) {
- return "<li>"
- + container.escapeExpression(container.lambda(depth0, depth0))
- + "</li>";
-},"50":function(container,depth0,helpers,partials,data) {
- var stack1;
-
- return ((stack1 = helpers.each.call(depth0 != null ? depth0 : (container.nullContext || {}),((stack1 = (depth0 != null ? depth0.definition : depth0)) != null ? stack1.glossary : stack1),{"name":"each","hash":{},"fn":container.program(20, data, 0),"inverse":container.noop,"data":data})) != null ? stack1 : "");
-},"52":function(container,depth0,helpers,partials,data) {
- var stack1;
-
- return container.escapeExpression(container.lambda(((stack1 = ((stack1 = (depth0 != null ? depth0.definition : depth0)) != null ? stack1.glossary : stack1)) != null ? stack1["0"] : stack1), depth0));
-},"54":function(container,depth0,helpers,partials,data,blockParams,depths) {
- var stack1;
-
- return ((stack1 = helpers["if"].call(depth0 != null ? depth0 : (container.nullContext || {}),(depth0 != null ? depth0.group : depth0),{"name":"if","hash":{},"fn":container.program(55, data, 0, blockParams, depths),"inverse":container.program(65, data, 0, blockParams, depths),"data":data})) != null ? stack1 : "");
-},"55":function(container,depth0,helpers,partials,data,blockParams,depths) {
- var stack1;
-
- return ((stack1 = helpers["if"].call(depth0 != null ? depth0 : (container.nullContext || {}),((stack1 = ((stack1 = (depth0 != null ? depth0.definition : depth0)) != null ? stack1.definitions : stack1)) != null ? stack1["1"] : stack1),{"name":"if","hash":{},"fn":container.program(56, data, 0, blockParams, depths),"inverse":container.program(63, data, 0, blockParams, depths),"data":data})) != null ? stack1 : "");
-},"56":function(container,depth0,helpers,partials,data,blockParams,depths) {
- var stack1;
-
- return ((stack1 = helpers["if"].call(depth0 != null ? depth0 : (container.nullContext || {}),(depth0 != null ? depth0.html : depth0),{"name":"if","hash":{},"fn":container.program(57, data, 0, blockParams, depths),"inverse":container.program(60, data, 0, blockParams, depths),"data":data})) != null ? stack1 : "");
-},"57":function(container,depth0,helpers,partials,data,blockParams,depths) {
- var stack1;
-
- return "<ol>"
- + ((stack1 = helpers.each.call(depth0 != null ? depth0 : (container.nullContext || {}),((stack1 = (depth0 != null ? depth0.definition : depth0)) != null ? stack1.definitions : stack1),{"name":"each","hash":{},"fn":container.program(58, data, 0, blockParams, depths),"inverse":container.noop,"data":data})) != null ? stack1 : "")
- + "</ol>";
-},"58":function(container,depth0,helpers,partials,data,blockParams,depths) {
- var stack1;
-
- return "<li>"
- + ((stack1 = container.invokePartial(partials["glossary-single"],depth0,{"name":"glossary-single","hash":{"brief":(depths[1] != null ? depths[1].brief : depths[1]),"html":(depths[1] != null ? depths[1].html : depths[1])},"data":data,"helpers":helpers,"partials":partials,"decorators":container.decorators})) != null ? stack1 : "")
- + "</li>";
-},"60":function(container,depth0,helpers,partials,data,blockParams,depths) {
- var stack1;
-
- return ((stack1 = helpers.each.call(depth0 != null ? depth0 : (container.nullContext || {}),((stack1 = (depth0 != null ? depth0.definition : depth0)) != null ? stack1.definitions : stack1),{"name":"each","hash":{},"fn":container.program(61, data, 0, blockParams, depths),"inverse":container.noop,"data":data})) != null ? stack1 : "");
-},"61":function(container,depth0,helpers,partials,data,blockParams,depths) {
- var stack1;
-
- return " * "
- + ((stack1 = container.invokePartial(partials["glossary-single"],depth0,{"name":"glossary-single","hash":{"brief":(depths[1] != null ? depths[1].brief : depths[1]),"html":(depths[1] != null ? depths[1].html : depths[1])},"data":data,"helpers":helpers,"partials":partials,"decorators":container.decorators})) != null ? stack1 : "");
-},"63":function(container,depth0,helpers,partials,data) {
- var stack1;
-
- return ((stack1 = container.invokePartial(partials["glossary-single"],((stack1 = ((stack1 = (depth0 != null ? depth0.definition : depth0)) != null ? stack1.definitions : stack1)) != null ? stack1["0"] : stack1),{"name":"glossary-single","hash":{"brief":(depth0 != null ? depth0.brief : depth0),"html":(depth0 != null ? depth0.html : depth0)},"data":data,"helpers":helpers,"partials":partials,"decorators":container.decorators})) != null ? stack1 : "");
-},"65":function(container,depth0,helpers,partials,data) {
- var stack1;
-
- return ((stack1 = container.invokePartial(partials["glossary-single"],(depth0 != null ? depth0.definition : depth0),{"name":"glossary-single","hash":{"brief":(depth0 != null ? depth0.brief : depth0),"html":(depth0 != null ? depth0.html : depth0)},"data":data,"helpers":helpers,"partials":partials,"decorators":container.decorators})) != null ? stack1 : "");
-},"67":function(container,depth0,helpers,partials,data) {
- return "</div>";
-},"69":function(container,depth0,helpers,partials,data) {
- var stack1;
-
- return ((stack1 = container.invokePartial(partials.glossary,depth0,{"name":"glossary","hash":{"brief":true},"data":data,"helpers":helpers,"partials":partials,"decorators":container.decorators})) != null ? stack1 : "");
-},"71":function(container,depth0,helpers,partials,data) {
- var stack1;
-
- return ((stack1 = helpers.each.call(depth0 != null ? depth0 : (container.nullContext || {}),((stack1 = (depth0 != null ? depth0.definition : depth0)) != null ? stack1.kunyomi : stack1),{"name":"each","hash":{},"fn":container.program(20, data, 0),"inverse":container.noop,"data":data})) != null ? stack1 : "");
-},"73":function(container,depth0,helpers,partials,data) {
- var stack1;
-
- return ((stack1 = helpers.each.call(depth0 != null ? depth0 : (container.nullContext || {}),((stack1 = (depth0 != null ? depth0.definition : depth0)) != null ? stack1.onyomi : stack1),{"name":"each","hash":{},"fn":container.program(20, data, 0),"inverse":container.noop,"data":data})) != null ? stack1 : "");
-},"75":function(container,depth0,helpers,partials,data) {
- var stack1;
-
- return ((stack1 = helpers.unless.call(depth0 != null ? depth0 : (container.nullContext || {}),(depth0 != null ? depth0.modeTermKana : depth0),{"name":"unless","hash":{},"fn":container.program(30, data, 0),"inverse":container.noop,"data":data})) != null ? stack1 : "");
-},"77":function(container,depth0,helpers,partials,data) {
- var stack1;
-
- return ((stack1 = helpers["if"].call(depth0 != null ? depth0 : (container.nullContext || {}),((stack1 = (depth0 != null ? depth0.definition : depth0)) != null ? stack1.cloze : stack1),{"name":"if","hash":{},"fn":container.program(78, data, 0),"inverse":container.noop,"data":data})) != null ? stack1 : "");
-},"78":function(container,depth0,helpers,partials,data) {
- var stack1;
-
- return container.escapeExpression(container.lambda(((stack1 = ((stack1 = (depth0 != null ? depth0.definition : depth0)) != null ? stack1.cloze : stack1)) != null ? stack1.sentence : stack1), depth0));
-},"80":function(container,depth0,helpers,partials,data) {
- var stack1;
-
- return ((stack1 = helpers["if"].call(depth0 != null ? depth0 : (container.nullContext || {}),((stack1 = (depth0 != null ? depth0.definition : depth0)) != null ? stack1.cloze : stack1),{"name":"if","hash":{},"fn":container.program(81, data, 0),"inverse":container.noop,"data":data})) != null ? stack1 : "");
-},"81":function(container,depth0,helpers,partials,data) {
- var stack1;
-
- return container.escapeExpression(container.lambda(((stack1 = ((stack1 = (depth0 != null ? depth0.definition : depth0)) != null ? stack1.cloze : stack1)) != null ? stack1.prefix : stack1), depth0));
-},"83":function(container,depth0,helpers,partials,data) {
- var stack1;
-
- return ((stack1 = helpers["if"].call(depth0 != null ? depth0 : (container.nullContext || {}),((stack1 = (depth0 != null ? depth0.definition : depth0)) != null ? stack1.cloze : stack1),{"name":"if","hash":{},"fn":container.program(84, data, 0),"inverse":container.noop,"data":data})) != null ? stack1 : "");
-},"84":function(container,depth0,helpers,partials,data) {
- var stack1;
-
- return container.escapeExpression(container.lambda(((stack1 = ((stack1 = (depth0 != null ? depth0.definition : depth0)) != null ? stack1.cloze : stack1)) != null ? stack1.body : stack1), depth0));
-},"86":function(container,depth0,helpers,partials,data) {
- var stack1;
-
- return ((stack1 = helpers["if"].call(depth0 != null ? depth0 : (container.nullContext || {}),((stack1 = (depth0 != null ? depth0.definition : depth0)) != null ? stack1.cloze : stack1),{"name":"if","hash":{},"fn":container.program(87, data, 0),"inverse":container.noop,"data":data})) != null ? stack1 : "");
-},"87":function(container,depth0,helpers,partials,data) {
- var stack1;
-
- return container.escapeExpression(container.lambda(((stack1 = ((stack1 = (depth0 != null ? depth0.definition : depth0)) != null ? stack1.cloze : stack1)) != null ? stack1.suffix : stack1), depth0));
-},"89":function(container,depth0,helpers,partials,data) {
- var stack1;
-
- return ((stack1 = helpers.each.call(depth0 != null ? depth0 : (container.nullContext || {}),((stack1 = (depth0 != null ? depth0.definition : depth0)) != null ? stack1.tags : stack1),{"name":"each","hash":{},"fn":container.program(5, data, 0),"inverse":container.noop,"data":data})) != null ? stack1 : "");
-},"91":function(container,depth0,helpers,partials,data) {
- var stack1;
-
- return ((stack1 = helpers["if"].call(depth0 != null ? depth0 : (container.nullContext || {}),(depth0 != null ? depth0.html : depth0),{"name":"if","hash":{},"fn":container.program(92, data, 0),"inverse":container.program(94, data, 0),"data":data})) != null ? stack1 : "");
-},"92":function(container,depth0,helpers,partials,data) {
- var stack1, alias1=container.lambda, alias2=container.escapeExpression;
-
- return "<a href=\""
- + alias2(alias1(((stack1 = (depth0 != null ? depth0.definition : depth0)) != null ? stack1.url : stack1), depth0))
- + "\">"
- + alias2(alias1(((stack1 = (depth0 != null ? depth0.definition : depth0)) != null ? stack1.url : stack1), depth0))
- + "</a>";
-},"94":function(container,depth0,helpers,partials,data) {
- var stack1;
-
- return container.escapeExpression(container.lambda(((stack1 = (depth0 != null ? depth0.definition : depth0)) != null ? stack1.url : stack1), depth0));
-},"compiler":[7,">= 4.0.0"],"main":function(container,depth0,helpers,partials,data,blockParams,depths) {
- var stack1;
-
- return "\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n"
- + ((stack1 = container.invokePartial(helpers.lookup.call(depth0 != null ? depth0 : (container.nullContext || {}),depth0,"marker",{"name":"lookup","hash":{},"data":data}),depth0,{"data":data,"helpers":helpers,"partials":partials,"decorators":container.decorators})) != null ? stack1 : "");
-},"main_d": function(fn, props, container, depth0, data, blockParams, depths) {
-
- var decorators = container.decorators;
-
- fn = decorators.inline(fn,props,container,{"name":"inline","hash":{},"fn":container.program(1, data, 0, blockParams, depths),"inverse":container.noop,"args":["glossary-single"],"data":data}) || fn;
- fn = decorators.inline(fn,props,container,{"name":"inline","hash":{},"fn":container.program(22, data, 0, blockParams, depths),"inverse":container.noop,"args":["audio"],"data":data}) || fn;
- fn = decorators.inline(fn,props,container,{"name":"inline","hash":{},"fn":container.program(24, data, 0, blockParams, depths),"inverse":container.noop,"args":["character"],"data":data}) || fn;
- fn = decorators.inline(fn,props,container,{"name":"inline","hash":{},"fn":container.program(26, data, 0, blockParams, depths),"inverse":container.noop,"args":["dictionary"],"data":data}) || fn;
- fn = decorators.inline(fn,props,container,{"name":"inline","hash":{},"fn":container.program(28, data, 0, blockParams, depths),"inverse":container.noop,"args":["expression"],"data":data}) || fn;
- fn = decorators.inline(fn,props,container,{"name":"inline","hash":{},"fn":container.program(34, data, 0, blockParams, depths),"inverse":container.noop,"args":["furigana"],"data":data}) || fn;
- fn = decorators.inline(fn,props,container,{"name":"inline","hash":{},"fn":container.program(40, data, 0, blockParams, depths),"inverse":container.noop,"args":["furigana-plain"],"data":data}) || fn;
- fn = decorators.inline(fn,props,container,{"name":"inline","hash":{},"fn":container.program(42, data, 0, blockParams, depths),"inverse":container.noop,"args":["glossary"],"data":data}) || fn;
- fn = decorators.inline(fn,props,container,{"name":"inline","hash":{},"fn":container.program(69, data, 0, blockParams, depths),"inverse":container.noop,"args":["glossary-brief"],"data":data}) || fn;
- fn = decorators.inline(fn,props,container,{"name":"inline","hash":{},"fn":container.program(71, data, 0, blockParams, depths),"inverse":container.noop,"args":["kunyomi"],"data":data}) || fn;
- fn = decorators.inline(fn,props,container,{"name":"inline","hash":{},"fn":container.program(73, data, 0, blockParams, depths),"inverse":container.noop,"args":["onyomi"],"data":data}) || fn;
- fn = decorators.inline(fn,props,container,{"name":"inline","hash":{},"fn":container.program(75, data, 0, blockParams, depths),"inverse":container.noop,"args":["reading"],"data":data}) || fn;
- fn = decorators.inline(fn,props,container,{"name":"inline","hash":{},"fn":container.program(77, data, 0, blockParams, depths),"inverse":container.noop,"args":["sentence"],"data":data}) || fn;
- fn = decorators.inline(fn,props,container,{"name":"inline","hash":{},"fn":container.program(80, data, 0, blockParams, depths),"inverse":container.noop,"args":["cloze-prefix"],"data":data}) || fn;
- fn = decorators.inline(fn,props,container,{"name":"inline","hash":{},"fn":container.program(83, data, 0, blockParams, depths),"inverse":container.noop,"args":["cloze-body"],"data":data}) || fn;
- fn = decorators.inline(fn,props,container,{"name":"inline","hash":{},"fn":container.program(86, data, 0, blockParams, depths),"inverse":container.noop,"args":["cloze-suffix"],"data":data}) || fn;
- fn = decorators.inline(fn,props,container,{"name":"inline","hash":{},"fn":container.program(89, data, 0, blockParams, depths),"inverse":container.noop,"args":["tags"],"data":data}) || fn;
- fn = decorators.inline(fn,props,container,{"name":"inline","hash":{},"fn":container.program(91, data, 0, blockParams, depths),"inverse":container.noop,"args":["url"],"data":data}) || fn;
- return fn;
- }
-
-,"useDecorators":true,"usePartial":true,"useData":true,"useDepths":true});
templates['kanji.html'] = template({"1":function(container,depth0,helpers,partials,data) {
var stack1, helper, alias1=depth0 != null ? depth0 : (container.nullContext || {});
diff --git a/ext/bg/settings.html b/ext/bg/settings.html
index 8798aeb1..0a5c205c 100644
--- a/ext/bg/settings.html
+++ b/ext/bg/settings.html
@@ -8,8 +8,7 @@
<style>
#anki-spinner, #anki-general, #anki-error,
#dict-spinner, #dict-error, #dict-warning, #dict-purge-progress, #dict-import-progress,
- #debug,
- .options-advanced {
+ #debug, .options-advanced {
display: none;
}
@@ -19,6 +18,12 @@
border-right: 1px #ddd solid;
padding: 10px;
}
+
+ #field-templates {
+ font-family: monospace;
+ overflow-x: hidden;
+ white-space: pre;
+ }
</style>
</head>
<body>
@@ -175,10 +180,6 @@
</div>
<div id="anki-general">
- <div class="checkbox options-advanced">
- <label><input type="checkbox" id="generate-html-cards"> Generate HTML cards</label>
- </div>
-
<div class="form-group">
<label for="card-tags">Card tags (comma or space separated)</label>
<input type="text" id="card-tags" class="form-control">
@@ -246,28 +247,38 @@
</table>
</div>
</div>
+
+ <div class="options-advanced">
+ <p class="help-block">
+ Fields are formatted using the <a href="http://handlebarsjs.com/">Handlebars.js</a> template rendering
+ engine. Advanced users can modify these templates for ultimate control of what information gets included in
+ their Anki cards. If you encounter problems with your changes you can always <a href="#" id="field-templates-reset">reset to default</a>
+ template settings.
+ </p>
+ <textarea class="form-control" rows="10" id="field-templates"></textarea>
+ </div>
</div>
</div>
+ </div>
- <div>
- <h3>Support Development</h3>
-
- <p class="help-block">
- Yomichan is provided to you <em>completely free</em> of charge. Unlike numerous other "free" services, you are not
- shown ads, pestered with "offers", or have your browser usage information analyzed and sold to third parties.
- </p>
- <p class="help-block">
- If you find Yomichan useful, please consider making a small donation as a way to show your appreciation for the
- countless hours that I have devoted to this extension.
- </p>
- <p>
- <a href="https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=4DBTN9A3CUAFN" target="_blank"><img src="/bg/img/paypal.gif" alt></a>
- </p>
- </div>
+ <div>
+ <h3>Support Development</h3>
- <pre id="debug"></pre>
+ <p class="help-block">
+ Yomichan is provided to you <em>completely free</em> of charge. Unlike numerous other "free" services, you are not
+ shown ads, pestered with "offers", or have your browser usage information analyzed and sold to third parties.
+ </p>
+ <p class="help-block">
+ If you find Yomichan useful, please consider making a small donation as a way to show your appreciation for the
+ countless hours that I have devoted to this extension.
+ </p>
+ <p>
+ <a href="https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=4DBTN9A3CUAFN" target="_blank"><img src="/bg/img/paypal.gif" alt></a>
+ </p>
</div>
+ <pre id="debug"></pre>
+
<div class="pull-right">
<small><a href="https://foosoft.net/projects/yomichan/" target="_blank">Homepage</a> &bull; <a href="legal.html">Legal</a></small>
</div>
diff --git a/ext/fg/js/api.js b/ext/fg/js/api.js
index 151882eb..4b4d9d74 100644
--- a/ext/fg/js/api.js
+++ b/ext/fg/js/api.js
@@ -45,8 +45,8 @@ function apiNoteView(noteId) {
return utilInvoke('noteView', {noteId});
}
-function apiTemplateRender(template, data) {
- return utilInvoke('templateRender', {data, template});
+function apiTemplateRender(template, data, dynamic) {
+ return utilInvoke('templateRender', {data, template, dynamic});
}
function apiCommandExec(command) {
diff --git a/ext/manifest.json b/ext/manifest.json
index fbd413e6..7ff76437 100644
--- a/ext/manifest.json
+++ b/ext/manifest.json
@@ -1,7 +1,7 @@
{
"manifest_version": 2,
"name": "Yomichan",
- "version": "1.3.4",
+ "version": "1.3.5",
"description": "Japanese dictionary with Anki integration",
"icons": {"16": "mixed/img/icon16.png", "48": "mixed/img/icon48.png", "128": "mixed/img/icon128.png"},
@@ -49,6 +49,7 @@
}
},
"web_accessible_resources": ["fg/float.html"],
+ "content_security_policy": "script-src 'self' 'unsafe-eval'; object-src 'self'",
"applications": {
"gecko": {
"id": "alex@foosoft.net",