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}` | 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. 日本語[にほんご]).
|
`{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}` | 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).
|
`{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.
|
`{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.
|
`{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/translator.js"></script>
|
||||||
<script src="/bg/js/util.js"></script>
|
<script src="/bg/js/util.js"></script>
|
||||||
<script src="/mixed/js/audio-system.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="/mixed/js/object-property-accessor.js"></script>
|
||||||
|
|
||||||
<script src="/bg/js/background-main.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~}}
|
{{~context.document.title~}}
|
||||||
{{/inline}}
|
{{/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") ~}}
|
{{~> (lookup . "marker") ~}}
|
||||||
|
@ -15,6 +15,10 @@
|
|||||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
/* global
|
||||||
|
* DictionaryDataUtil
|
||||||
|
*/
|
||||||
|
|
||||||
class AnkiNoteBuilder {
|
class AnkiNoteBuilder {
|
||||||
constructor({anki, audioSystem, renderTemplate}) {
|
constructor({anki, audioSystem, renderTemplate}) {
|
||||||
this._anki = anki;
|
this._anki = anki;
|
||||||
@ -39,9 +43,10 @@ class AnkiNoteBuilder {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const data = this.createNoteData(definition, mode, context, options);
|
||||||
const formattedFieldValuePromises = [];
|
const formattedFieldValuePromises = [];
|
||||||
for (const [, fieldValue] of modeOptionsFieldEntries) {
|
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);
|
formattedFieldValuePromises.push(formattedFieldValuePromise);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -55,10 +60,14 @@ class AnkiNoteBuilder {
|
|||||||
return note;
|
return note;
|
||||||
}
|
}
|
||||||
|
|
||||||
async formatField(field, definition, mode, context, options, templates, errors=null) {
|
createNoteData(definition, mode, context, options) {
|
||||||
const data = {
|
const pitches = DictionaryDataUtil.getPitchAccentInfos(definition);
|
||||||
|
const pitchCount = pitches.reduce((i, v) => i + v.pitches.length, 0);
|
||||||
|
return {
|
||||||
marker: null,
|
marker: null,
|
||||||
definition,
|
definition,
|
||||||
|
pitches,
|
||||||
|
pitchCount,
|
||||||
group: options.general.resultOutputMode === 'group',
|
group: options.general.resultOutputMode === 'group',
|
||||||
merge: options.general.resultOutputMode === 'merge',
|
merge: options.general.resultOutputMode === 'merge',
|
||||||
modeTermKanji: mode === 'term-kanji',
|
modeTermKanji: mode === 'term-kanji',
|
||||||
@ -67,6 +76,9 @@ class AnkiNoteBuilder {
|
|||||||
compactGlossaries: options.general.compactGlossaries,
|
compactGlossaries: options.general.compactGlossaries,
|
||||||
context
|
context
|
||||||
};
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
async formatField(field, data, templates, errors=null) {
|
||||||
const pattern = /\{([\w-]+)\}/g;
|
const pattern = /\{([\w-]+)\}/g;
|
||||||
return await AnkiNoteBuilder.stringReplaceAsync(field, pattern, async (g0, marker) => {
|
return await AnkiNoteBuilder.stringReplaceAsync(field, pattern, async (g0, marker) => {
|
||||||
data.marker = marker;
|
data.marker = marker;
|
||||||
|
@ -380,31 +380,83 @@ class OptionsUtil {
|
|||||||
return [
|
return [
|
||||||
{
|
{
|
||||||
async: false,
|
async: false,
|
||||||
update: (options) => {
|
update: this._updateVersion1.bind(this)
|
||||||
// Version 1 changes:
|
|
||||||
// Added options.global.database.prefixWildcardsSupported = false
|
|
||||||
options.global = {
|
|
||||||
database: {
|
|
||||||
prefixWildcardsSupported: false
|
|
||||||
}
|
|
||||||
};
|
|
||||||
return options;
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
async: false,
|
async: false,
|
||||||
update: (options) => {
|
update: this._updateVersion2.bind(this)
|
||||||
// Version 2 changes:
|
},
|
||||||
// Legacy profile update process moved into this upgrade function.
|
{
|
||||||
for (const profile of options.profiles) {
|
async: true,
|
||||||
if (!Array.isArray(profile.conditionGroups)) {
|
update: this._updateVersion3.bind(this)
|
||||||
profile.conditionGroups = [];
|
|
||||||
}
|
|
||||||
profile.options = this._legacyProfileUpdateUpdateVersion(profile.options);
|
|
||||||
}
|
|
||||||
return options;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static _updateVersion1(options) {
|
||||||
|
// Version 1 changes:
|
||||||
|
// Added options.global.database.prefixWildcardsSupported = false.
|
||||||
|
options.global = {
|
||||||
|
database: {
|
||||||
|
prefixWildcardsSupported: false
|
||||||
|
}
|
||||||
|
};
|
||||||
|
return options;
|
||||||
|
}
|
||||||
|
|
||||||
|
static _updateVersion2(options) {
|
||||||
|
// Version 2 changes:
|
||||||
|
// Legacy profile update process moved into this upgrade function.
|
||||||
|
for (const profile of options.profiles) {
|
||||||
|
if (!Array.isArray(profile.conditionGroups)) {
|
||||||
|
profile.conditionGroups = [];
|
||||||
|
}
|
||||||
|
profile.options = this._legacyProfileUpdateUpdateVersion(profile.options);
|
||||||
|
}
|
||||||
|
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;
|
let templates = options.anki.fieldTemplates;
|
||||||
if (typeof templates !== 'string') { templates = this._defaultFieldTemplates; }
|
if (typeof templates !== 'string') { templates = this._defaultFieldTemplates; }
|
||||||
const ankiNoteBuilder = new AnkiNoteBuilder({renderTemplate: api.templateRender.bind(api)});
|
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) {
|
} catch (e) {
|
||||||
exceptions.push(e);
|
exceptions.push(e);
|
||||||
|
@ -54,6 +54,9 @@ class AnkiController {
|
|||||||
'furigana-plain',
|
'furigana-plain',
|
||||||
'glossary',
|
'glossary',
|
||||||
'glossary-brief',
|
'glossary-brief',
|
||||||
|
'pitch-accents',
|
||||||
|
'pitch-accent-graphs',
|
||||||
|
'pitch-accent-positions',
|
||||||
'reading',
|
'reading',
|
||||||
'screenshot',
|
'screenshot',
|
||||||
'sentence',
|
'sentence',
|
||||||
@ -63,6 +66,9 @@ class AnkiController {
|
|||||||
case 'kanji':
|
case 'kanji':
|
||||||
return [
|
return [
|
||||||
'character',
|
'character',
|
||||||
|
'cloze-body',
|
||||||
|
'cloze-prefix',
|
||||||
|
'cloze-suffix',
|
||||||
'dictionary',
|
'dictionary',
|
||||||
'document-title',
|
'document-title',
|
||||||
'glossary',
|
'glossary',
|
||||||
|
@ -82,7 +82,10 @@ class TemplateRenderer {
|
|||||||
['get', this._get.bind(this)],
|
['get', this._get.bind(this)],
|
||||||
['set', this._set.bind(this)],
|
['set', this._set.bind(this)],
|
||||||
['scope', this._scope.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) {
|
for (const [name, helper] of helpers) {
|
||||||
@ -316,21 +319,20 @@ class TemplateRenderer {
|
|||||||
_set(context, ...args) {
|
_set(context, ...args) {
|
||||||
switch (args.length) {
|
switch (args.length) {
|
||||||
case 2:
|
case 2:
|
||||||
{
|
{
|
||||||
const [key, options] = args;
|
const [key, options] = args;
|
||||||
const value = options.fn(context);
|
const value = options.fn(context);
|
||||||
this._stateStack[this._stateStack.length - 1].set(key, value);
|
this._stateStack[this._stateStack.length - 1].set(key, value);
|
||||||
return value;
|
}
|
||||||
}
|
break;
|
||||||
case 3:
|
case 3:
|
||||||
{
|
{
|
||||||
const [key, value] = args;
|
const [key, value] = args;
|
||||||
this._stateStack[this._stateStack.length - 1].set(key, value);
|
this._stateStack[this._stateStack.length - 1].set(key, value);
|
||||||
return value;
|
}
|
||||||
}
|
break;
|
||||||
default:
|
|
||||||
return void 0;
|
|
||||||
}
|
}
|
||||||
|
return '';
|
||||||
}
|
}
|
||||||
|
|
||||||
_scope(context, options) {
|
_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);
|
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/profiles.js"></script>
|
||||||
<script src="/bg/js/settings/settings-controller.js"></script>
|
<script src="/bg/js/settings/settings-controller.js"></script>
|
||||||
<script src="/bg/js/settings/storage.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/object-property-accessor.js"></script>
|
||||||
<script src="/mixed/js/task-accumulator.js"></script>
|
<script src="/mixed/js/task-accumulator.js"></script>
|
||||||
<script src="/mixed/js/dom-data-binder.js"></script>
|
<script src="/mixed/js/dom-data-binder.js"></script>
|
||||||
|
Loading…
Reference in New Issue
Block a user