diff options
Diffstat (limited to 'ext')
| -rw-r--r-- | ext/css/settings.css | 7 | ||||
| -rw-r--r-- | ext/data/templates/anki-field-templates-upgrade-v21.handlebars | 161 | ||||
| -rw-r--r-- | ext/data/templates/default-anki-field-templates.handlebars | 54 | ||||
| -rw-r--r-- | ext/js/background/backend.js | 20 | ||||
| -rw-r--r-- | ext/js/data/options-util.js | 35 | ||||
| -rw-r--r-- | ext/js/pages/welcome-main.js | 7 | ||||
| -rw-r--r-- | ext/js/templates/sandbox/anki-template-renderer.js | 54 | ||||
| -rw-r--r-- | ext/welcome.html | 27 | 
8 files changed, 284 insertions, 81 deletions
| diff --git a/ext/css/settings.css b/ext/css/settings.css index eaebc3af..a2618d88 100644 --- a/ext/css/settings.css +++ b/ext/css/settings.css @@ -2167,6 +2167,13 @@ button.hotkey-list-item-enabled-button[data-scope-count='0'] {      display: none;  } +.warn-custom-templates-notification { +    border: 1px solid var(--danger-color); +} +:root:not([data-warn-custom-templates=true]) .warn-custom-templates-notification { +    display: none; +} +  .test-anki-note-viewer-container {      margin-top: 0.85em;      display: flex; diff --git a/ext/data/templates/anki-field-templates-upgrade-v21.handlebars b/ext/data/templates/anki-field-templates-upgrade-v21.handlebars new file mode 100644 index 00000000..33c4dc6c --- /dev/null +++ b/ext/data/templates/anki-field-templates-upgrade-v21.handlebars @@ -0,0 +1,161 @@ +{{<<<<<<<}} +{{#formatGlossary ../dictionary}}{{{.}}}{{/formatGlossary}} +{{=======}} +{{formatGlossary ../dictionary .}} +{{>>>>>>>}} + +{{<<<<<<<}} +{{~#furigana}}{{{.}}}{{/furigana~}} +{{=======}} +{{~furigana .~}} +{{>>>>>>>}} + +{{<<<<<<<}} +{{#furigana}}{{{definition}}}{{/furigana}} +{{=======}} +{{furigana definition}} +{{>>>>>>>}} + +{{<<<<<<<}} +{{~#furigana expression reading~}}{{~/furigana~}} +{{=======}} +{{~furigana expression reading~}} +{{>>>>>>>}} + +{{<<<<<<<}} +{{~#furigana expression reading}}{{/furigana~}} +{{=======}} +{{~furigana expression reading~}} +{{>>>>>>>}} + +{{<<<<<<<}} +{{~#furiganaPlain}}{{{.}}}{{/furiganaPlain~}} +{{=======}} +{{~furiganaPlain .~}} +{{>>>>>>>}} + +{{<<<<<<<}} +{{#furiganaPlain}}{{{definition}}}{{/furiganaPlain}} +{{=======}} +{{furiganaPlain definition}} +{{>>>>>>>}} + +{{<<<<<<<}} +{{~#furiganaPlain expression reading~}}{{~/furiganaPlain~}} +{{=======}} +{{~furiganaPlain expression reading~}} +{{>>>>>>>}} + +{{<<<<<<<}} +{{~#furiganaPlain expression reading}}{{/furiganaPlain~}} +{{=======}} +{{~furiganaPlain expression reading~}} +{{>>>>>>>}} + +{{<<<<<<<}} +{{#getMedia "audio"}}{{/getMedia}} +{{=======}} +{{getMedia "audio"}} +{{>>>>>>>}} + +{{<<<<<<<}} +{{#getMedia "screenshot"}}{{/getMedia}} +{{=======}} +{{getMedia "screenshot"}} +{{>>>>>>>}} + +{{<<<<<<<}} +{{#getMedia "clipboardImage"}}{{/getMedia}} +{{=======}} +{{getMedia "clipboardImage"}} +{{>>>>>>>}} + +{{<<<<<<<}} +{{#getMedia "clipboardText"}}{{/getMedia}} +{{=======}} +{{getMedia "clipboardText"}} +{{>>>>>>>}} + +{{<<<<<<<}} +{{#getMedia "selectionText"}}{{/getMedia}} +{{=======}} +{{getMedia "selectionText"}} +{{>>>>>>>}} + +{{<<<<<<<}} +{{#getMedia "textFurigana" definition.cloze.sentence escape=false}}{{/getMedia}} +{{=======}} +{{getMedia "textFurigana" definition.cloze.sentence escape=false}} +{{>>>>>>>}} + +{{<<<<<<<}} +{{~#pronunciation format=format reading=reading downstepPosition=position nasalPositions=nasalPositions devoicePositions=devoicePositions~}}{{~/pronunciation~}} +{{=======}} +{{~pronunciation format=format reading=reading downstepPosition=position nasalPositions=nasalPositions devoicePositions=devoicePositions~}} +{{>>>>>>>}} + +{{<<<<<<<}} +{{~#set "any" false}}{{/set~}} +{{=======}} +{{~set "any" false~}} +{{>>>>>>>}} + +{{<<<<<<<}} +{{~#set "any" true}}{{/set~}} +{{=======}} +{{~set "any" true~}} +{{>>>>>>>}} + +{{<<<<<<<}} +{{~#set "previousDictionary" dictionary~}}{{~/set~}} +{{=======}} +{{~set "previousDictionary" dictionary~}} +{{>>>>>>>}} + +{{<<<<<<<}} +{{~#set "exclusive" (spread exclusiveExpressions exclusiveReadings)}}{{/set~}} +{{=======}} +{{~set "exclusive" (spread exclusiveExpressions exclusiveReadings)~}} +{{>>>>>>>}} + +{{<<<<<<<}} +{{~#set "separator" ""~}}{{/set~}} +{{=======}} +{{~set "separator" ""~}} +{{>>>>>>>}} + +{{<<<<<<<}} +{{~#get "separator"}}{{/get~}} +{{=======}} +{{~get "separator"~}} +{{>>>>>>>}} + +{{<<<<<<<}} +{{~#set "found" false}}{{/set~}} +{{=======}} +{{~set "found" false~}} +{{>>>>>>>}} + +{{<<<<<<<}} +{{~#set "found" true}}{{/set~}} +{{=======}} +{{~set "found" true~}} +{{>>>>>>>}} + +{{<<<<<<<}} +{{~#set "first" true}}{{/set~}} +{{=======}} +{{~set "first" true~}} +{{>>>>>>>}} + +{{<<<<<<<}} +{{~#set "first" false~}}{{~/set~}} +{{=======}} +{{~set "first" false~}} +{{>>>>>>>}} + +{{<<<<<<<}} +{{~#set (concat "used_" .) true~}}{{~/set~}} +{{=======}} +{{~set (concat "used_" .) true~}} +{{>>>>>>>}} diff --git a/ext/data/templates/default-anki-field-templates.handlebars b/ext/data/templates/default-anki-field-templates.handlebars index 31d5d13f..d94f6d70 100644 --- a/ext/data/templates/default-anki-field-templates.handlebars +++ b/ext/data/templates/default-anki-field-templates.handlebars @@ -1,19 +1,19 @@  {{#*inline "glossary-single"}}      {{~#unless brief~}}          {{~#scope~}} -            {{~#set "any" false}}{{/set~}} +            {{~set "any" false~}}              {{~#each definitionTags~}}                  {{~#if (op "||" (op "!" @root.compactTags) (op "!" redundant))~}}                      {{~#if (get "any")}}, {{else}}<i>({{/if~}}                      {{name}} -                    {{~#set "any" true}}{{/set~}} +                    {{~set "any" true~}}                  {{~/if~}}              {{~/each~}}              {{~#unless noDictionaryTag~}}                  {{~#if (op "||" (op "!" @root.compactTags) (op "!==" dictionary (get "previousDictionary")))~}}                      {{~#if (get "any")}}, {{else}}<i>({{/if~}}                      {{dictionary}} -                    {{~#set "any" true}}{{/set~}} +                    {{~set "any" true~}}                  {{~/if~}}              {{~/unless~}}              {{~#if (get "any")}})</i> {{/if~}} @@ -21,18 +21,18 @@          {{~#if only~}}({{#each only}}{{.}}{{#unless @last}}, {{/unless}}{{/each}} only) {{/if~}}      {{~/unless~}}      {{~#if (op "<=" glossary.length 1)~}} -        {{#each glossary}}{{#formatGlossary ../dictionary}}{{{.}}}{{/formatGlossary}}{{/each}} +        {{#each glossary}}{{formatGlossary ../dictionary .}}{{/each}}      {{~else if @root.compactGlossaries~}} -        {{#each glossary}}{{#formatGlossary ../dictionary}}{{{.}}}{{/formatGlossary}}{{#unless @last}} | {{/unless}}{{/each}} +        {{#each glossary}}{{formatGlossary ../dictionary .}}{{#unless @last}} | {{/unless}}{{/each}}      {{~else~}} -        <ul>{{#each glossary}}<li>{{#formatGlossary ../dictionary}}{{{.}}}{{/formatGlossary}}</li>{{/each}}</ul> +        <ul>{{#each glossary}}<li>{{formatGlossary ../dictionary .}}</li>{{/each}}</ul>      {{~/if~}} -    {{~#set "previousDictionary" dictionary~}}{{~/set~}} +    {{~set "previousDictionary" dictionary~}}  {{/inline}}  {{#*inline "audio"}}      {{~#if (hasMedia "audio")~}} -        [sound:{{#getMedia "audio"}}{{/getMedia}}] +        [sound:{{getMedia "audio"}}]      {{~/if~}}  {{/inline}} @@ -78,22 +78,22 @@  {{#*inline "furigana"}}      {{~#if merge~}}          {{~#each definition.expressions~}} -            <span class="expression-{{termFrequency}}">{{~#furigana}}{{{.}}}{{/furigana~}}</span> +            <span class="expression-{{termFrequency}}">{{~furigana .~}}</span>              {{~#unless @last}}、{{/unless~}}          {{~/each~}}      {{~else~}} -        {{#furigana}}{{{definition}}}{{/furigana}} +        {{furigana definition}}      {{~/if~}}  {{/inline}}  {{#*inline "furigana-plain"}}      {{~#if merge~}}          {{~#each definition.expressions~}} -            <span class="expression-{{termFrequency}}">{{~#furiganaPlain}}{{{.}}}{{/furiganaPlain~}}</span> +            <span class="expression-{{termFrequency}}">{{~furiganaPlain .~}}</span>              {{~#unless @last}}、{{/unless~}}          {{~/each~}}      {{~else~}} -        {{#furiganaPlain}}{{{definition}}}{{/furiganaPlain}} +        {{furiganaPlain definition}}      {{~/if~}}  {{/inline}} @@ -174,7 +174,7 @@  {{#*inline "screenshot"}}      {{~#if (hasMedia "screenshot")~}} -        <img src="{{#getMedia "screenshot"}}{{/getMedia}}" /> +        <img src="{{getMedia "screenshot"}}" />      {{~/if~}}  {{/inline}} @@ -184,16 +184,16 @@  {{! Pitch Accents }}  {{#*inline "pitch-accent-item"}} -    {{~#pronunciation format=format reading=reading downstepPosition=position nasalPositions=nasalPositions devoicePositions=devoicePositions~}}{{~/pronunciation~}} +    {{~pronunciation format=format reading=reading downstepPosition=position nasalPositions=nasalPositions devoicePositions=devoicePositions~}}  {{/inline}}  {{#*inline "pitch-accent-item-disambiguation"}}      {{~#scope~}} -        {{~#set "exclusive" (spread exclusiveExpressions exclusiveReadings)}}{{/set~}} +        {{~set "exclusive" (spread exclusiveExpressions exclusiveReadings)~}}          {{~#if (op ">" (property (get "exclusive") "length") 0)~}} -            {{~#set "separator" ""~}}{{/set~}} +            {{~set "separator" ""~}}              <em>({{#each (get "exclusive")~}} -                {{~#get "separator"}}{{/get~}}{{{.}}} +                {{~get "separator"~}}{{{.}}}              {{~/each}} only) </em>          {{~/if~}}      {{~/scope~}} @@ -231,12 +231,12 @@  {{#*inline "clipboard-image"}}      {{~#if (hasMedia "clipboardImage")~}} -        <img src="{{#getMedia "clipboardImage"}}{{/getMedia}}" /> +        <img src="{{getMedia "clipboardImage"}}" />      {{~/if~}}  {{/inline}}  {{#*inline "clipboard-text"}} -    {{~#if (hasMedia "clipboardText")}}{{#getMedia "clipboardText"}}{{/getMedia}}{{/if~}} +    {{~#if (hasMedia "clipboardText")}}{{getMedia "clipboardText"}}{{/if~}}  {{/inline}}  {{#*inline "conjugation"}} @@ -255,7 +255,7 @@              <li>              {{~#if (op "!==" ../definition.type "kanji")~}}                  {{~#if (op "||" (op ">" ../uniqueExpressions.length 1) (op ">" ../uniqueReadings.length 1))~}}( -                    {{~#furigana expression reading~}}{{~/furigana~}} +                    {{~furigana expression reading~}}                  ) {{/if~}}              {{~/if~}}              {{~dictionary}}: {{frequency~}} @@ -267,10 +267,10 @@  {{#*inline "stroke-count"}}      {{~#scope~}} -        {{~#set "found" false}}{{/set~}} +        {{~set "found" false~}}          {{~#each definition.stats.misc~}}              {{~#if (op "===" name "strokes")~}} -                {{~#set "found" true}}{{/set~}} +                {{~set "found" true~}}                  Stroke count: {{value}}              {{~/if~}}          {{~/each~}} @@ -295,14 +295,14 @@  {{#*inline "part-of-speech"}}      {{~#scope~}}          {{~#if (op "!==" definition.type "kanji")~}} -            {{~#set "first" true}}{{/set~}} +            {{~set "first" true~}}              {{~#each definition.expressions~}}                  {{~#each wordClasses~}}                      {{~#unless (get (concat "used_" .))~}}                          {{~> part-of-speech-pretty . ~}}                          {{~#unless (get "first")}}, {{/unless~}} -                        {{~#set (concat "used_" .) true~}}{{~/set~}} -                        {{~#set "first" false~}}{{~/set~}} +                        {{~set (concat "used_" .) true~}} +                        {{~set "first" false~}}                      {{~/unless~}}                  {{~/each~}}              {{~/each~}} @@ -316,13 +316,13 @@  {{/inline}}  {{#*inline "selection-text"}} -    {{~#if (hasMedia "selectionText")}}{{#getMedia "selectionText"}}{{/getMedia}}{{/if~}} +    {{~#if (hasMedia "selectionText")}}{{getMedia "selectionText"}}{{/if~}}  {{/inline}}  {{#*inline "sentence-furigana"}}      {{~#if definition.cloze~}}          {{~#if (hasMedia "textFurigana" definition.cloze.sentence)~}} -            {{#getMedia "textFurigana" definition.cloze.sentence escape=false}}{{/getMedia}} +            {{getMedia "textFurigana" definition.cloze.sentence escape=false}}          {{~else~}}              {{definition.cloze.sentence}}          {{~/if~}} diff --git a/ext/js/background/backend.js b/ext/js/background/backend.js index 308ae4d5..8e8e6945 100644 --- a/ext/js/background/backend.js +++ b/ext/js/background/backend.js @@ -2127,20 +2127,12 @@ class Backend {      }      async _openWelcomeGuidePageOnce() { -        if (isObject(chrome.storage) && isObject(chrome.storage.session)) { -            // Chrome -            chrome.storage.session.get(['openedWelcomePage']).then((result) => { -                if (!result.openedWelcomePage) { -                    this._openWelcomeGuidePage(); -                    chrome.storage.session.set({'openedWelcomePage': true}); -                } -            }); -        } else { -            // Firefox (storage.session is not supported yet) -            // NOTE: This means that the welcome page will repeatedly open in Firefox -            // until they support storage.session. -            this._openWelcomeGuidePage(); -        } +        chrome.storage.session.get(['openedWelcomePage']).then((result) => { +            if (!result.openedWelcomePage) { +                this._openWelcomeGuidePage(); +                chrome.storage.session.set({'openedWelcomePage': true}); +            } +        });      }      async _openWelcomeGuidePage() { diff --git a/ext/js/data/options-util.js b/ext/js/data/options-util.js index 2674701f..1f2ffb05 100644 --- a/ext/js/data/options-util.js +++ b/ext/js/data/options-util.js @@ -470,7 +470,8 @@ class OptionsUtil {              {async: false, update: this._updateVersion17.bind(this)},              {async: false, update: this._updateVersion18.bind(this)},              {async: false, update: this._updateVersion19.bind(this)}, -            {async: false, update: this._updateVersion20.bind(this)} +            {async: false, update: this._updateVersion20.bind(this)}, +            {async: true,  update: this._updateVersion21.bind(this)}          ];          if (typeof targetVersion === 'number' && targetVersion < result.length) {              result.splice(targetVersion); @@ -997,4 +998,36 @@ class OptionsUtil {          }          return options;      } + +    async _updateVersion21(options) { +        await this._applyAnkiFieldTemplatesPatch(options, '/data/templates/anki-field-templates-upgrade-v21.handlebars'); + +        let customTemplates = false; +        for (const {options: profileOptions} of options.profiles) { +            if (profileOptions.anki.fieldTemplates !== null) { +                customTemplates = true; +            } +        } + +        if (customTemplates && isObject(chrome.storage)) { +            chrome.storage.session.set({'needsCustomTemplatesWarning': true}); +            await this._createTab(chrome.runtime.getURL('/welcome.html')); +            chrome.storage.session.set({'openedWelcomePage': true}); +        } + +        return options; +    } + +    _createTab(url) { +        return new Promise((resolve, reject) => { +            chrome.tabs.create({url}, (tab) => { +                const e = chrome.runtime.lastError; +                if (e) { +                    reject(new Error(e.message)); +                } else { +                    resolve(tab); +                } +            }); +        }); +    }  } diff --git a/ext/js/pages/welcome-main.js b/ext/js/pages/welcome-main.js index 521ce2c2..8039dae5 100644 --- a/ext/js/pages/welcome-main.js +++ b/ext/js/pages/welcome-main.js @@ -58,6 +58,13 @@ async function setupGenericSettingsController(genericSettingController) {          setupEnvironmentInfo(); +        chrome.storage.session.get({'needsCustomTemplatesWarning': false}).then((result) => { +            if (result.needsCustomTemplatesWarning) { +                document.documentElement.dataset.warnCustomTemplates = 'true'; +                chrome.storage.session.remove(['needsCustomTemplatesWarning']); +            } +        }); +          const preparePromises = [];          const modalController = new ModalController(); diff --git a/ext/js/templates/sandbox/anki-template-renderer.js b/ext/js/templates/sandbox/anki-template-renderer.js index 789f0942..766c7798 100644 --- a/ext/js/templates/sandbox/anki-template-renderer.js +++ b/ext/js/templates/sandbox/anki-template-renderer.js @@ -68,9 +68,7 @@ class AnkiTemplateRenderer {              ['dumpObject',       this._dumpObject.bind(this)],              ['furigana',         this._furigana.bind(this)],              ['furiganaPlain',    this._furiganaPlain.bind(this)], -            ['kanjiLinks',       this._kanjiLinks.bind(this)],              ['multiLine',        this._multiLine.bind(this)], -            ['sanitizeCssClass', this._sanitizeCssClass.bind(this)],              ['regexReplace',     this._regexReplace.bind(this)],              ['regexMatch',       this._regexMatch.bind(this)],              ['mergeTags',        this._mergeTags.bind(this)], @@ -132,10 +130,14 @@ class AnkiTemplateRenderer {          return Handlebars.Utils.escapeExpression(text);      } +    _safeString(text) { +        return new Handlebars.SafeString(text); +    } +      // Template helpers -    _dumpObject(context, options) { -        const dump = JSON.stringify(options.fn(context), null, 4); +    _dumpObject(context, object) { +        const dump = JSON.stringify(object, null, 4);          return this._escape(dump);      } @@ -145,14 +147,16 @@ class AnkiTemplateRenderer {          let result = '';          for (const {text, reading: reading2} of segs) { -            if (reading2.length > 0) { -                result += `<ruby>${text}<rt>${reading2}</rt></ruby>`; +            const safeText = this._escape(text); +            const safeReading = this._escape(reading2); +            if (safeReading.length > 0) { +                result += `<ruby>${safeText}<rt>${safeReading}</rt></ruby>`;              } else { -                result += text; +                result += safeText;              }          } -        return result; +        return this._safeString(result);      }      _furiganaPlain(context, ...args) { @@ -173,29 +177,16 @@ class AnkiTemplateRenderer {      }      _getFuriganaExpressionAndReading(context, ...args) { -        const options = args[args.length - 1];          if (args.length >= 3) {              return {expression: args[0], reading: args[1]}; -        } else { -            const {expression, reading} = options.fn(context); +        } else if (args.length === 2) { +            const {expression, reading} = args[0];              return {expression, reading}; +        } else { +            return void 0;          }      } -    _kanjiLinks(context, options) { -        const jp = this._japaneseUtil; -        let result = ''; -        for (const c of options.fn(context)) { -            if (jp.isCodePointKanji(c.codePointAt(0))) { -                result += `<a href="#" class="kanji-link">${c}</a>`; -            } else { -                result += c; -            } -        } - -        return result; -    } -      _stringToMultiLineHtml(string) {          return string.split('\n').join('<br>');      } @@ -204,10 +195,6 @@ class AnkiTemplateRenderer {          return this._stringToMultiLineHtml(options.fn(context));      } -    _sanitizeCssClass(context, options) { -        return options.fn(context).replace(/[^_a-z0-9\u00a0-\uffff]/ig, '_'); -    } -      _regexReplace(context, ...args) {          // Usage:          // {{#regexReplace regex string [flags] [content]...}}content{{/regexReplace}} @@ -219,7 +206,7 @@ class AnkiTemplateRenderer {          const options = args[argCount];          let value = typeof options.fn === 'function' ? options.fn(context) : '';          if (argCount > 3) { -            value = `${args.slice(3).join('')}${value}`; +            value = `${args.slice(3, -1).join('')}${value}`;          }          if (argCount > 1) {              try { @@ -243,7 +230,7 @@ class AnkiTemplateRenderer {          const options = args[argCount];          let value = typeof options.fn === 'function' ? options.fn(context) : '';          if (argCount > 2) { -            value = `${args.slice(2).join('')}${value}`; +            value = `${args.slice(2, -1).join('')}${value}`;          }          if (argCount > 0) {              try { @@ -490,7 +477,7 @@ class AnkiTemplateRenderer {          this._normalizeHtml(container, styleApplier, datasetKeyIgnorePattern);          const result = container.innerHTML;          container.textContent = ''; -        return result; +        return this._safeString(result);      }      _normalizeHtml(root, styleApplier, datasetKeyIgnorePattern) { @@ -543,9 +530,8 @@ class AnkiTemplateRenderer {          return instance;      } -    _formatGlossary(context, dictionary, options) { +    _formatGlossary(context, dictionary, content, options) {          const data = options.data.root; -        const content = options.fn(context);          if (typeof content === 'string') { return this._stringToMultiLineHtml(this._escape(content)); }          if (!(typeof content === 'object' && content !== null)) { return ''; }          switch (content.type) { diff --git a/ext/welcome.html b/ext/welcome.html index 14e98367..56167866 100644 --- a/ext/welcome.html +++ b/ext/welcome.html @@ -25,6 +25,19 @@      <h1>Welcome to Yomitan!</h1> +    <!-- Notifications --> +    <div class="settings-group settings-group-top-margin warn-custom-templates-notification"> +      <div class="settings-item"> +        <div class="settings-item-inner settings-item-inner-wrappable"><div class="settings-item-left"><div class="settings-item-label"> +              <p> +                There are custom Anki templates in your settings. Note that <a href="https://github.com/themoeway/yomitan#custom-templates" target="_blank" rel="noopener noreferrer">some syntax has changed from previous versions of Yomitan.</a> +                Please ensure that your custom templates are using the updated syntax. +              </p> +          </div></div></div> +      </div> +    </div> + +    <!-- Content -->      <h2>Here are some basics to get started</h2>      <div class="settings-group">          <div class="settings-item"> @@ -49,10 +62,9 @@          <div class="settings-item">              <div class="settings-item-inner"><div class="settings-item-left"><div class="settings-item-label">                  Yomitan requires one or more dictionaries to be installed in order to look up terms, kanji, and other information. -                Several downloadable dictionaries can be found on the <a href="https://github.com/themoeway/yomitan#dictionaries" target="_blank" rel="noopener noreferrer">Yomitan homepage</a>, -                allowing you to choose the dictionaries most relevant for you. +                Several downloadable dictionaries can be found on the <a href="https://github.com/themoeway/yomitan#dictionaries" target="_blank" rel="noopener noreferrer">Yomitan homepage</a>.                  Dictionaries can be configured using the button below, -                or later from the the <a href="/settings.html" rel="noopener">Settings</a> page. +                or later from the <a href="/settings.html" rel="noopener">Settings</a> page.              </div></div></div>              <div class="settings-item-children settings-item-children-group">                  <div class="settings-item settings-item-button" data-modal-action="show,dictionaries"><div class="settings-item-inner"> @@ -67,12 +79,17 @@          </div>          <div class="settings-item">              <div class="settings-item-inner"><div class="settings-item-left"><div class="settings-item-label"> -                You can also import an exported collection of dictionaries to migrate from a different device or browser from the <a href="/settings.html#!backup">Backup section of the Settings</a> page. +                You can also import an exported collection of dictionaries from the <a href="/settings.html#!backup">Backup section of the Settings</a> page.                  <br><br> -                If you are migrating from Yomichan, you may be particularly interested in migrating your data from Yomichan into Yomitan. +                If you are migrating from Yomichan, you may be interested in importing your data into Yomitan.                  Please follow instructions from <a href="https://github.com/themoeway/yomitan#migrating-from-yomichan" target="_blank" rel="noopener noreferrer">Yomitan's README</a> for that. + +                <br><br> + +                If you are using or planning to use custom templates for Anki note creation, note that <a href="https://github.com/themoeway/yomitan#custom-templates" target="_blank" rel="noopener noreferrer">some syntax has changed from Yomichan and Yomibaba.</a> +                Please ensure that your custom templates are using the updated syntax.              </div></div></div>          </div>          <div class="settings-item"> |