Pitch accent Anki field templates (#701)
* Template helper updates * Add pitch data to exported field formatting data * Reuse note data * Add no-op * Set up pitch accent templates * Refactor version update functions * Implement upgrade process for new Anki templates * Consistency * Update README and anki.js to have matching markers
This commit is contained in:
parent
1e839cd230
commit
838fd211c6
@ -163,6 +163,10 @@ Flashcard fields can be configured with the following steps:
|
||||
`{furigana}` | Term expressed as kanji with furigana displayed above it (e.g. <ruby>日本語<rt>にほんご</rt></ruby>).
|
||||
`{furigana-plain}` | Term expressed as kanji with furigana displayed next to it in brackets (e.g. 日本語[にほんご]).
|
||||
`{glossary}` | List of definitions for the term (output format depends on whether running in *grouped* mode).
|
||||
`{glossary-brief}` | List of definitions for the term in a more compact format.
|
||||
`{pitch-accents}` | List of pitch accent downstep notations for the term.
|
||||
`{pitch-accent-graphs}` | List of pitch accent graphs for the term.
|
||||
`{pitch-accent-positions}` | List of accent downstep positions for the term as a number.
|
||||
`{reading}` | Kana reading for the term (empty for terms where the expression is the reading).
|
||||
`{screenshot}` | Screenshot of the web page taken at the time the term was added.
|
||||
`{sentence}` | Sentence, quote, or phrase that the term appears in from the source content.
|
||||
|
@ -46,6 +46,7 @@
|
||||
<script src="/bg/js/translator.js"></script>
|
||||
<script src="/bg/js/util.js"></script>
|
||||
<script src="/mixed/js/audio-system.js"></script>
|
||||
<script src="/mixed/js/dictionary-data-util.js"></script>
|
||||
<script src="/mixed/js/object-property-accessor.js"></script>
|
||||
|
||||
<script src="/bg/js/background-main.js"></script>
|
||||
|
109
ext/bg/data/anki-field-templates-upgrade-v2.handlebars
Normal file
109
ext/bg/data/anki-field-templates-upgrade-v2.handlebars
Normal file
@ -0,0 +1,109 @@
|
||||
{{! Pitch Accents }}
|
||||
{{#*inline "pitch-accent-item-downstep-notation"}}
|
||||
{{~#scope~}}
|
||||
<span>
|
||||
{{~#set "style1a"~}}display:inline-block;position:relative;{{~/set~}}
|
||||
{{~#set "style1b"~}}padding-right:0.1em;margin-right:0.1em;{{~/set~}}
|
||||
{{~#set "style2a"~}}display:block;user-select:none;pointer-events:none;position:absolute;top:0.1em;left:0;right:0;height:0;border-top:0.1em solid;{{~/set~}}
|
||||
{{~#set "style2b"~}}right:-0.1em;height:0.4em;border-right:0.1em solid;{{~/set~}}
|
||||
{{~#each (getKanaMorae reading)~}}
|
||||
{{~#set "style1"}}{{#get "style1a"}}{{/get}}{{/set~}}
|
||||
{{~#set "style2"}}{{/set~}}
|
||||
{{~#if (isMoraPitchHigh @index ../position)}}
|
||||
{{~#set "style2"}}{{#get "style2a"}}{{/get}}{{/set~}}
|
||||
{{~#if (op "!" (isMoraPitchHigh (op "+" @index 1) ../position))~}}
|
||||
{{~#set "style1" (op "+" (get "style1") (get "style1b"))}}{{/set~}}
|
||||
{{~#set "style2" (op "+" (get "style2") (get "style2b"))}}{{/set~}}
|
||||
{{~/if~}}
|
||||
{{~/if~}}
|
||||
<span style="{{#get "style1"}}{{/get}}">{{{.}}}<span style="{{#get "style2"}}{{/get}}"></span></span>
|
||||
{{~/each~}}
|
||||
</span>
|
||||
{{~/scope~}}
|
||||
{{/inline}}
|
||||
|
||||
{{#*inline "pitch-accent-item-graph-position-x"}}{{#op "+" 25 (op "*" index 50)}}{{/op}}{{/inline}}
|
||||
{{#*inline "pitch-accent-item-graph-position-y"}}{{#op "+" 25 (op "?:" (isMoraPitchHigh index position) 0 50)}}{{/op}}{{/inline}}
|
||||
{{#*inline "pitch-accent-item-graph-position"}}{{> pitch-accent-item-graph-position-x index=index position=position}} {{> pitch-accent-item-graph-position-y index=index position=position}}{{/inline}}
|
||||
{{#*inline "pitch-accent-item-graph"}}
|
||||
{{~#scope~}}
|
||||
{{~#set "morae" (getKanaMorae reading)}}{{/set~}}
|
||||
{{~#set "morae-count" (property (get "morae") "length")}}{{/set~}}
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 {{#op "+" 50 (op "*" 50 (get "morae-count"))}}{{/op}} 100" style="display:inline-block;height:2em;">
|
||||
<defs>
|
||||
<g id="term-pitch-accent-graph-dot"><circle cx="0" cy="0" r="15" style="fill:#000;stroke:#000;stroke-width:5;" /></g>
|
||||
<g id="term-pitch-accent-graph-dot-downstep"><circle cx="0" cy="0" r="15" style="fill:none;stroke:#000;stroke-width:5;" /><circle cx="0" cy="0" r="5" style="fill:none;stroke:#000;stroke-width:5;" /></g>
|
||||
<g id="term-pitch-accent-graph-triangle"><path d="M0 13 L15 -13 L-15 -13 Z" style="fill:none;stroke:#000;stroke-width:5;" /></g>
|
||||
</defs>
|
||||
<path style="fill:none;stroke:#000;stroke-width:5;" d="
|
||||
{{~#set "cmd" "M"}}{{/set~}}
|
||||
{{~#each (get "morae")~}}
|
||||
{{~#get "cmd"}}{{/get~}}
|
||||
{{~> pitch-accent-item-graph-position index=@index position=../position~}}
|
||||
{{~#set "cmd" "L"}}{{/set~}}
|
||||
{{~/each~}}
|
||||
"></path>
|
||||
<path style="fill:none;stroke:#000;stroke-width:5;stroke-dasharray:5 5;" d="M{{> pitch-accent-item-graph-position index=(op "-" (get "morae-count") 1) position=position}} L{{> pitch-accent-item-graph-position index=(get "morae-count") position=position}}"></path>
|
||||
{{#each (get "morae")}}
|
||||
<use href="{{#if (op "&&" (isMoraPitchHigh @index ../position) (op "!" (isMoraPitchHigh (op "+" @index 1) ../position)))}}#term-pitch-accent-graph-dot-downstep{{else}}#term-pitch-accent-graph-dot{{/if}}" x="{{> pitch-accent-item-graph-position-x index=@index position=../position}}" y="{{> pitch-accent-item-graph-position-y index=@index position=../position}}"></use>
|
||||
{{/each}}
|
||||
<use href="#term-pitch-accent-graph-triangle" x="{{> pitch-accent-item-graph-position-x index=(get "morae-count") position=position}}" y="{{> pitch-accent-item-graph-position-y index=(get "morae-count") position=position}}"></use>
|
||||
</svg>
|
||||
{{~/scope~}}
|
||||
{{/inline}}
|
||||
|
||||
{{#*inline "pitch-accent-item-position"~}}
|
||||
<span>[{{position}}]</span>
|
||||
{{~/inline}}
|
||||
|
||||
{{#*inline "pitch-accent-item"}}
|
||||
{{~#if (op "==" format "downstep-notation")~}}
|
||||
{{~> pitch-accent-item-downstep-notation~}}
|
||||
{{~else if (op "==" format "graph")~}}
|
||||
{{~> pitch-accent-item-graph~}}
|
||||
{{~else if (op "==" format "position")~}}
|
||||
{{~> pitch-accent-item-position~}}
|
||||
{{~/if~}}
|
||||
{{/inline}}
|
||||
|
||||
{{#*inline "pitch-accent-item-disambiguation"}}
|
||||
{{~#scope~}}
|
||||
{{~#set "exclusive" (spread exclusiveExpressions exclusiveReadings)}}{{/set~}}
|
||||
{{~#if (op ">" (property (get "exclusive") "length") 0)~}}
|
||||
{{~#set "separator" ""~}}{{/set~}}
|
||||
<em>({{#each (get "exclusive")~}}
|
||||
{{~#get "separator"}}{{/get~}}{{{.}}}
|
||||
{{~/each}} only) </em>
|
||||
{{~/if~}}
|
||||
{{~/scope~}}
|
||||
{{/inline}}
|
||||
|
||||
{{#*inline "pitch-accent-list"}}
|
||||
{{~#if (op ">" pitchCount 0)~}}
|
||||
{{~#if (op ">" pitchCount 1)~}}<ol>{{~/if~}}
|
||||
{{~#each pitches~}}
|
||||
{{~#each pitches~}}
|
||||
{{~#if (op ">" ../../pitchCount 1)~}}<li>{{~/if~}}
|
||||
{{~> pitch-accent-item-disambiguation~}}
|
||||
{{~> pitch-accent-item format=../../format~}}
|
||||
{{~#if (op ">" ../../pitchCount 1)~}}</li>{{~/if~}}
|
||||
{{~/each~}}
|
||||
{{~/each~}}
|
||||
{{~#if (op ">" pitchCount 1)~}}</ol>{{~/if~}}
|
||||
{{~else~}}
|
||||
No pitch accent data
|
||||
{{~/if~}}
|
||||
{{/inline}}
|
||||
|
||||
{{#*inline "pitch-accents"}}
|
||||
{{~> pitch-accent-list format='downstep-notation'~}}
|
||||
{{/inline}}
|
||||
|
||||
{{#*inline "pitch-accent-graphs"}}
|
||||
{{~> pitch-accent-list format='graph'~}}
|
||||
{{/inline}}
|
||||
|
||||
{{#*inline "pitch-accent-positions"}}
|
||||
{{~> pitch-accent-list format='position'~}}
|
||||
{{/inline}}
|
||||
{{! End Pitch Accents }}
|
@ -166,4 +166,114 @@
|
||||
{{~context.document.title~}}
|
||||
{{/inline}}
|
||||
|
||||
{{! Pitch Accents }}
|
||||
{{#*inline "pitch-accent-item-downstep-notation"}}
|
||||
{{~#scope~}}
|
||||
<span>
|
||||
{{~#set "style1a"~}}display:inline-block;position:relative;{{~/set~}}
|
||||
{{~#set "style1b"~}}padding-right:0.1em;margin-right:0.1em;{{~/set~}}
|
||||
{{~#set "style2a"~}}display:block;user-select:none;pointer-events:none;position:absolute;top:0.1em;left:0;right:0;height:0;border-top:0.1em solid;{{~/set~}}
|
||||
{{~#set "style2b"~}}right:-0.1em;height:0.4em;border-right:0.1em solid;{{~/set~}}
|
||||
{{~#each (getKanaMorae reading)~}}
|
||||
{{~#set "style1"}}{{#get "style1a"}}{{/get}}{{/set~}}
|
||||
{{~#set "style2"}}{{/set~}}
|
||||
{{~#if (isMoraPitchHigh @index ../position)}}
|
||||
{{~#set "style2"}}{{#get "style2a"}}{{/get}}{{/set~}}
|
||||
{{~#if (op "!" (isMoraPitchHigh (op "+" @index 1) ../position))~}}
|
||||
{{~#set "style1" (op "+" (get "style1") (get "style1b"))}}{{/set~}}
|
||||
{{~#set "style2" (op "+" (get "style2") (get "style2b"))}}{{/set~}}
|
||||
{{~/if~}}
|
||||
{{~/if~}}
|
||||
<span style="{{#get "style1"}}{{/get}}">{{{.}}}<span style="{{#get "style2"}}{{/get}}"></span></span>
|
||||
{{~/each~}}
|
||||
</span>
|
||||
{{~/scope~}}
|
||||
{{/inline}}
|
||||
|
||||
{{#*inline "pitch-accent-item-graph-position-x"}}{{#op "+" 25 (op "*" index 50)}}{{/op}}{{/inline}}
|
||||
{{#*inline "pitch-accent-item-graph-position-y"}}{{#op "+" 25 (op "?:" (isMoraPitchHigh index position) 0 50)}}{{/op}}{{/inline}}
|
||||
{{#*inline "pitch-accent-item-graph-position"}}{{> pitch-accent-item-graph-position-x index=index position=position}} {{> pitch-accent-item-graph-position-y index=index position=position}}{{/inline}}
|
||||
{{#*inline "pitch-accent-item-graph"}}
|
||||
{{~#scope~}}
|
||||
{{~#set "morae" (getKanaMorae reading)}}{{/set~}}
|
||||
{{~#set "morae-count" (property (get "morae") "length")}}{{/set~}}
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 {{#op "+" 50 (op "*" 50 (get "morae-count"))}}{{/op}} 100" style="display:inline-block;height:2em;">
|
||||
<defs>
|
||||
<g id="term-pitch-accent-graph-dot"><circle cx="0" cy="0" r="15" style="fill:#000;stroke:#000;stroke-width:5;" /></g>
|
||||
<g id="term-pitch-accent-graph-dot-downstep"><circle cx="0" cy="0" r="15" style="fill:none;stroke:#000;stroke-width:5;" /><circle cx="0" cy="0" r="5" style="fill:none;stroke:#000;stroke-width:5;" /></g>
|
||||
<g id="term-pitch-accent-graph-triangle"><path d="M0 13 L15 -13 L-15 -13 Z" style="fill:none;stroke:#000;stroke-width:5;" /></g>
|
||||
</defs>
|
||||
<path style="fill:none;stroke:#000;stroke-width:5;" d="
|
||||
{{~#set "cmd" "M"}}{{/set~}}
|
||||
{{~#each (get "morae")~}}
|
||||
{{~#get "cmd"}}{{/get~}}
|
||||
{{~> pitch-accent-item-graph-position index=@index position=../position~}}
|
||||
{{~#set "cmd" "L"}}{{/set~}}
|
||||
{{~/each~}}
|
||||
"></path>
|
||||
<path style="fill:none;stroke:#000;stroke-width:5;stroke-dasharray:5 5;" d="M{{> pitch-accent-item-graph-position index=(op "-" (get "morae-count") 1) position=position}} L{{> pitch-accent-item-graph-position index=(get "morae-count") position=position}}"></path>
|
||||
{{#each (get "morae")}}
|
||||
<use href="{{#if (op "&&" (isMoraPitchHigh @index ../position) (op "!" (isMoraPitchHigh (op "+" @index 1) ../position)))}}#term-pitch-accent-graph-dot-downstep{{else}}#term-pitch-accent-graph-dot{{/if}}" x="{{> pitch-accent-item-graph-position-x index=@index position=../position}}" y="{{> pitch-accent-item-graph-position-y index=@index position=../position}}"></use>
|
||||
{{/each}}
|
||||
<use href="#term-pitch-accent-graph-triangle" x="{{> pitch-accent-item-graph-position-x index=(get "morae-count") position=position}}" y="{{> pitch-accent-item-graph-position-y index=(get "morae-count") position=position}}"></use>
|
||||
</svg>
|
||||
{{~/scope~}}
|
||||
{{/inline}}
|
||||
|
||||
{{#*inline "pitch-accent-item-position"~}}
|
||||
<span>[{{position}}]</span>
|
||||
{{~/inline}}
|
||||
|
||||
{{#*inline "pitch-accent-item"}}
|
||||
{{~#if (op "==" format "downstep-notation")~}}
|
||||
{{~> pitch-accent-item-downstep-notation~}}
|
||||
{{~else if (op "==" format "graph")~}}
|
||||
{{~> pitch-accent-item-graph~}}
|
||||
{{~else if (op "==" format "position")~}}
|
||||
{{~> pitch-accent-item-position~}}
|
||||
{{~/if~}}
|
||||
{{/inline}}
|
||||
|
||||
{{#*inline "pitch-accent-item-disambiguation"}}
|
||||
{{~#scope~}}
|
||||
{{~#set "exclusive" (spread exclusiveExpressions exclusiveReadings)}}{{/set~}}
|
||||
{{~#if (op ">" (property (get "exclusive") "length") 0)~}}
|
||||
{{~#set "separator" ""~}}{{/set~}}
|
||||
<em>({{#each (get "exclusive")~}}
|
||||
{{~#get "separator"}}{{/get~}}{{{.}}}
|
||||
{{~/each}} only) </em>
|
||||
{{~/if~}}
|
||||
{{~/scope~}}
|
||||
{{/inline}}
|
||||
|
||||
{{#*inline "pitch-accent-list"}}
|
||||
{{~#if (op ">" pitchCount 0)~}}
|
||||
{{~#if (op ">" pitchCount 1)~}}<ol>{{~/if~}}
|
||||
{{~#each pitches~}}
|
||||
{{~#each pitches~}}
|
||||
{{~#if (op ">" ../../pitchCount 1)~}}<li>{{~/if~}}
|
||||
{{~> pitch-accent-item-disambiguation~}}
|
||||
{{~> pitch-accent-item format=../../format~}}
|
||||
{{~#if (op ">" ../../pitchCount 1)~}}</li>{{~/if~}}
|
||||
{{~/each~}}
|
||||
{{~/each~}}
|
||||
{{~#if (op ">" pitchCount 1)~}}</ol>{{~/if~}}
|
||||
{{~else~}}
|
||||
No pitch accent data
|
||||
{{~/if~}}
|
||||
{{/inline}}
|
||||
|
||||
{{#*inline "pitch-accents"}}
|
||||
{{~> pitch-accent-list format='downstep-notation'~}}
|
||||
{{/inline}}
|
||||
|
||||
{{#*inline "pitch-accent-graphs"}}
|
||||
{{~> pitch-accent-list format='graph'~}}
|
||||
{{/inline}}
|
||||
|
||||
{{#*inline "pitch-accent-positions"}}
|
||||
{{~> pitch-accent-list format='position'~}}
|
||||
{{/inline}}
|
||||
{{! End Pitch Accents }}
|
||||
|
||||
{{~> (lookup . "marker") ~}}
|
||||
|
@ -15,6 +15,10 @@
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/* global
|
||||
* DictionaryDataUtil
|
||||
*/
|
||||
|
||||
class AnkiNoteBuilder {
|
||||
constructor({anki, audioSystem, renderTemplate}) {
|
||||
this._anki = anki;
|
||||
@ -39,9 +43,10 @@ class AnkiNoteBuilder {
|
||||
}
|
||||
};
|
||||
|
||||
const data = this.createNoteData(definition, mode, context, options);
|
||||
const formattedFieldValuePromises = [];
|
||||
for (const [, fieldValue] of modeOptionsFieldEntries) {
|
||||
const formattedFieldValuePromise = this.formatField(fieldValue, definition, mode, context, options, templates, null);
|
||||
const formattedFieldValuePromise = this.formatField(fieldValue, data, templates, null);
|
||||
formattedFieldValuePromises.push(formattedFieldValuePromise);
|
||||
}
|
||||
|
||||
@ -55,10 +60,14 @@ class AnkiNoteBuilder {
|
||||
return note;
|
||||
}
|
||||
|
||||
async formatField(field, definition, mode, context, options, templates, errors=null) {
|
||||
const data = {
|
||||
createNoteData(definition, mode, context, options) {
|
||||
const pitches = DictionaryDataUtil.getPitchAccentInfos(definition);
|
||||
const pitchCount = pitches.reduce((i, v) => i + v.pitches.length, 0);
|
||||
return {
|
||||
marker: null,
|
||||
definition,
|
||||
pitches,
|
||||
pitchCount,
|
||||
group: options.general.resultOutputMode === 'group',
|
||||
merge: options.general.resultOutputMode === 'merge',
|
||||
modeTermKanji: mode === 'term-kanji',
|
||||
@ -67,6 +76,9 @@ class AnkiNoteBuilder {
|
||||
compactGlossaries: options.general.compactGlossaries,
|
||||
context
|
||||
};
|
||||
}
|
||||
|
||||
async formatField(field, data, templates, errors=null) {
|
||||
const pattern = /\{([\w-]+)\}/g;
|
||||
return await AnkiNoteBuilder.stringReplaceAsync(field, pattern, async (g0, marker) => {
|
||||
data.marker = marker;
|
||||
|
@ -380,9 +380,22 @@ class OptionsUtil {
|
||||
return [
|
||||
{
|
||||
async: false,
|
||||
update: (options) => {
|
||||
update: this._updateVersion1.bind(this)
|
||||
},
|
||||
{
|
||||
async: false,
|
||||
update: this._updateVersion2.bind(this)
|
||||
},
|
||||
{
|
||||
async: true,
|
||||
update: this._updateVersion3.bind(this)
|
||||
}
|
||||
];
|
||||
}
|
||||
|
||||
static _updateVersion1(options) {
|
||||
// Version 1 changes:
|
||||
// Added options.global.database.prefixWildcardsSupported = false
|
||||
// Added options.global.database.prefixWildcardsSupported = false.
|
||||
options.global = {
|
||||
database: {
|
||||
prefixWildcardsSupported: false
|
||||
@ -390,10 +403,8 @@ class OptionsUtil {
|
||||
};
|
||||
return options;
|
||||
}
|
||||
},
|
||||
{
|
||||
async: false,
|
||||
update: (options) => {
|
||||
|
||||
static _updateVersion2(options) {
|
||||
// Version 2 changes:
|
||||
// Legacy profile update process moved into this upgrade function.
|
||||
for (const profile of options.profiles) {
|
||||
@ -404,7 +415,48 @@ class OptionsUtil {
|
||||
}
|
||||
return options;
|
||||
}
|
||||
|
||||
static async _updateVersion3(options) {
|
||||
// Version 3 changes:
|
||||
// Pitch accent Anki field templates added.
|
||||
let addition = null;
|
||||
for (const {options: profileOptions} of options.profiles) {
|
||||
const fieldTemplates = profileOptions.anki.fieldTemplates;
|
||||
if (fieldTemplates !== null) {
|
||||
if (addition === null) {
|
||||
addition = await this._updateVersion3GetAnkiFieldTemplates();
|
||||
}
|
||||
];
|
||||
profileOptions.anki.fieldTemplates = this._addFieldTemplatesBeforeEnd(fieldTemplates, addition);
|
||||
}
|
||||
}
|
||||
return options;
|
||||
}
|
||||
|
||||
static async _updateVersion3GetAnkiFieldTemplates() {
|
||||
const url = chrome.runtime.getURL('/bg/data/anki-field-templates-upgrade-v2.handlebars');
|
||||
const response = await fetch(url, {
|
||||
method: 'GET',
|
||||
mode: 'no-cors',
|
||||
cache: 'default',
|
||||
credentials: 'omit',
|
||||
redirect: 'follow',
|
||||
referrerPolicy: 'no-referrer'
|
||||
});
|
||||
return await response.text();
|
||||
}
|
||||
|
||||
static async _addFieldTemplatesBeforeEnd(fieldTemplates, addition) {
|
||||
const pattern = /[ \t]*\{\{~?>\s*\(\s*lookup\s*\.\s*"marker"\s*\)\s*~?\}\}/;
|
||||
const newline = '\n';
|
||||
let replaced = false;
|
||||
fieldTemplates = fieldTemplates.replace(pattern, (g0) => {
|
||||
replaced = true;
|
||||
return `${addition}${newline}${g0}`;
|
||||
});
|
||||
if (!replaced) {
|
||||
fieldTemplates += newline;
|
||||
fieldTemplates += addition;
|
||||
}
|
||||
return fieldTemplates;
|
||||
}
|
||||
}
|
||||
|
@ -144,7 +144,8 @@ class AnkiTemplatesController {
|
||||
let templates = options.anki.fieldTemplates;
|
||||
if (typeof templates !== 'string') { templates = this._defaultFieldTemplates; }
|
||||
const ankiNoteBuilder = new AnkiNoteBuilder({renderTemplate: api.templateRender.bind(api)});
|
||||
result = await ankiNoteBuilder.formatField(field, definition, mode, context, options, templates, exceptions);
|
||||
const data = ankiNoteBuilder.createNoteData(definition, mode, context, options);
|
||||
result = await ankiNoteBuilder.formatField(field, data, templates, exceptions);
|
||||
}
|
||||
} catch (e) {
|
||||
exceptions.push(e);
|
||||
|
@ -54,6 +54,9 @@ class AnkiController {
|
||||
'furigana-plain',
|
||||
'glossary',
|
||||
'glossary-brief',
|
||||
'pitch-accents',
|
||||
'pitch-accent-graphs',
|
||||
'pitch-accent-positions',
|
||||
'reading',
|
||||
'screenshot',
|
||||
'sentence',
|
||||
@ -63,6 +66,9 @@ class AnkiController {
|
||||
case 'kanji':
|
||||
return [
|
||||
'character',
|
||||
'cloze-body',
|
||||
'cloze-prefix',
|
||||
'cloze-suffix',
|
||||
'dictionary',
|
||||
'document-title',
|
||||
'glossary',
|
||||
|
@ -82,7 +82,10 @@ class TemplateRenderer {
|
||||
['get', this._get.bind(this)],
|
||||
['set', this._set.bind(this)],
|
||||
['scope', this._scope.bind(this)],
|
||||
['isMoraPitchHigh', this._isMoraPitchHigh.bind(this)]
|
||||
['property', this._property.bind(this)],
|
||||
['noop', this._noop.bind(this)],
|
||||
['isMoraPitchHigh', this._isMoraPitchHigh.bind(this)],
|
||||
['getKanaMorae', this._getKanaMorae.bind(this)]
|
||||
];
|
||||
|
||||
for (const [name, helper] of helpers) {
|
||||
@ -320,17 +323,16 @@ class TemplateRenderer {
|
||||
const [key, options] = args;
|
||||
const value = options.fn(context);
|
||||
this._stateStack[this._stateStack.length - 1].set(key, value);
|
||||
return value;
|
||||
}
|
||||
break;
|
||||
case 3:
|
||||
{
|
||||
const [key, value] = args;
|
||||
this._stateStack[this._stateStack.length - 1].set(key, value);
|
||||
return value;
|
||||
}
|
||||
default:
|
||||
return void 0;
|
||||
break;
|
||||
}
|
||||
return '';
|
||||
}
|
||||
|
||||
_scope(context, options) {
|
||||
@ -344,7 +346,30 @@ class TemplateRenderer {
|
||||
}
|
||||
}
|
||||
|
||||
_isMoraPitchHigh(context, position, index) {
|
||||
_property(context, ...args) {
|
||||
const ii = args.length - 1;
|
||||
if (ii <= 0) { return void 0; }
|
||||
|
||||
try {
|
||||
let value = args[0];
|
||||
for (let i = 1; i < ii; ++i) {
|
||||
value = value[args[i]];
|
||||
}
|
||||
return value;
|
||||
} catch (e) {
|
||||
return void 0;
|
||||
}
|
||||
}
|
||||
|
||||
_noop(context, options) {
|
||||
return options.fn(context);
|
||||
}
|
||||
|
||||
_isMoraPitchHigh(context, index, position) {
|
||||
return jp.isMoraPitchHigh(index, position);
|
||||
}
|
||||
|
||||
_getKanaMorae(context, text) {
|
||||
return jp.getKanaMorae(`${text}`);
|
||||
}
|
||||
}
|
||||
|
@ -1162,6 +1162,7 @@
|
||||
<script src="/bg/js/settings/profiles.js"></script>
|
||||
<script src="/bg/js/settings/settings-controller.js"></script>
|
||||
<script src="/bg/js/settings/storage.js"></script>
|
||||
<script src="/mixed/js/dictionary-data-util.js"></script>
|
||||
<script src="/mixed/js/object-property-accessor.js"></script>
|
||||
<script src="/mixed/js/task-accumulator.js"></script>
|
||||
<script src="/mixed/js/dom-data-binder.js"></script>
|
||||
|
Loading…
Reference in New Issue
Block a user