diff options
Diffstat (limited to 'ext')
| -rw-r--r-- | ext/bg/js/api.js | 14 | ||||
| -rw-r--r-- | ext/bg/js/backend.js | 4 | ||||
| -rw-r--r-- | ext/bg/js/dictionary.js | 10 | ||||
| -rw-r--r-- | ext/bg/js/handlebars.js | 19 | ||||
| -rw-r--r-- | ext/bg/js/options.js | 113 | ||||
| -rw-r--r-- | ext/bg/js/settings.js | 20 | ||||
| -rw-r--r-- | ext/bg/js/templates.js | 307 | ||||
| -rw-r--r-- | ext/bg/settings.html | 55 | ||||
| -rw-r--r-- | ext/fg/js/api.js | 4 | ||||
| -rw-r--r-- | ext/manifest.json | 3 | 
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> • <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", |