From 0506cfbee5443635ebd6ac79054b85f171775039 Mon Sep 17 00:00:00 2001 From: praschke Date: Tue, 17 Oct 2023 21:21:30 +0100 Subject: initial handlebars patch --- .../templates/anki-field-templates-upgrade-v21.handlebars | 0 ext/js/data/options-util.js | 8 +++++++- test/test-options-util.js | 15 +++++++++++++-- 3 files changed, 20 insertions(+), 3 deletions(-) create mode 100644 ext/data/templates/anki-field-templates-upgrade-v21.handlebars 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..e69de29b diff --git a/ext/js/data/options-util.js b/ext/js/data/options-util.js index 2674701f..7b050416 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,9 @@ class OptionsUtil { } return options; } + + async _updateVersion21(options) { + await this._applyAnkiFieldTemplatesPatch(options, '/data/templates/anki-field-templates-upgrade-v21.handlebars'); + return options; + } } diff --git a/test/test-options-util.js b/test/test-options-util.js index 2be6b2f7..068367a2 100644 --- a/test/test-options-util.js +++ b/test/test-options-util.js @@ -622,7 +622,7 @@ function createOptionsUpdatedTestData1() { } ], profileCurrent: 0, - version: 20, + version: 21, global: { database: { prefixWildcardsSupported: false @@ -689,7 +689,8 @@ async function testFieldTemplatesUpdate(extDir) { {version: 8, changes: loadDataFile('data/templates/anki-field-templates-upgrade-v8.handlebars')}, {version: 10, changes: loadDataFile('data/templates/anki-field-templates-upgrade-v10.handlebars')}, {version: 12, changes: loadDataFile('data/templates/anki-field-templates-upgrade-v12.handlebars')}, - {version: 13, changes: loadDataFile('data/templates/anki-field-templates-upgrade-v13.handlebars')} + {version: 13, changes: loadDataFile('data/templates/anki-field-templates-upgrade-v13.handlebars')}, + {version: 21, changes: loadDataFile('data/templates/anki-field-templates-upgrade-v21.handlebars')} ]; const getUpdateAdditions = (startVersion, targetVersion) => { let value = ''; @@ -1214,6 +1215,16 @@ async function testFieldTemplatesUpdate(extDir) { {{! End Pitch Accents }} <<>> +{{~> (lookup . "marker") ~}}`.trimStart() + }, + // block helper update + { + oldVersion: 20, + newVersion: 21, + old: ` +{{~> (lookup . "marker") ~}}`.trimStart(), + + expected: ` {{~> (lookup . "marker") ~}}`.trimStart() } ]; -- cgit v1.2.3 From 9a78edaee74a8355d49ec930c82e118518d5d625 Mon Sep 17 00:00:00 2001 From: praschke Date: Tue, 17 Oct 2023 21:23:47 +0100 Subject: fix: dumpObject --- docs/templates.md | 4 ++-- ext/js/templates/sandbox/anki-template-renderer.js | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/docs/templates.md b/docs/templates.md index 778b8e2d..c050889f 100644 --- a/docs/templates.md +++ b/docs/templates.md @@ -14,7 +14,7 @@ This function can be helpful for debugging values when creating templates.
Syntax: - {{#dumpObject}}<object>{{/dumpObject}} + {{dumpObject object}} * _`object`_
The object to convert. @@ -23,7 +23,7 @@ This function can be helpful for debugging values when creating templates. Example: ```handlebars -
{{#dumpObject}}{{.}}{{/dumpObject}}
+
{{dumpObject .}}
``` Output: diff --git a/ext/js/templates/sandbox/anki-template-renderer.js b/ext/js/templates/sandbox/anki-template-renderer.js index 789f0942..9e0bc8ed 100644 --- a/ext/js/templates/sandbox/anki-template-renderer.js +++ b/ext/js/templates/sandbox/anki-template-renderer.js @@ -134,8 +134,8 @@ class AnkiTemplateRenderer { // 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); } -- cgit v1.2.3 From ae91e2442d7b3746c633871ff956a8addd7046b5 Mon Sep 17 00:00:00 2001 From: praschke Date: Tue, 17 Oct 2023 21:41:45 +0100 Subject: fix: furigana and furiganaPlain --- docs/templates.md | 16 ++--- .../anki-field-templates-upgrade-v21.handlebars | 30 ++++++++ .../default-anki-field-templates.handlebars | 10 +-- ext/js/templates/sandbox/anki-template-renderer.js | 21 ++++-- test/test-options-util.js | 80 +++++++++++++++++++++- 5 files changed, 136 insertions(+), 21 deletions(-) diff --git a/docs/templates.md b/docs/templates.md index c050889f..bf5bd897 100644 --- a/docs/templates.md +++ b/docs/templates.md @@ -49,8 +49,8 @@ Converts a definition or expression/reading pair to its furigana representation.
Syntax: - {{#furigana}}<definition>{{/furigana}}
- {{#furigana expression reading}}{{/furigana}}
+ {{furigana definition}}
+ {{furigana expression reading}}
* _`definition`_
The definition to convert. @@ -63,8 +63,8 @@ Converts a definition or expression/reading pair to its furigana representation. Example: ```handlebars - {{#furigana}}{{.}}{{/furigana}} - {{#furigana "読む" "よむ"}}{{/furigana}} + {{furigana .}} + {{furigana "読む" "よむ"}} ``` Output: @@ -84,8 +84,8 @@ Converts a definition or expression/reading pair to its simplified furigana repr
Syntax: - {{#furiganaPlain}}<definition>{{/furigana}} - {{#furiganaPlain expression reading}}{{/furiganaPlain}}
+ {{furiganaPlain definition}} + {{furiganaPlain expression reading}}
* _`definition`_
The definition to convert. @@ -98,8 +98,8 @@ Converts a definition or expression/reading pair to its simplified furigana repr Example: ```handlebars - {{~#furiganaPlain~}}{{.}}{{~/furiganaPlain~}} - {{#furiganaPlain "読む" "よむ"}}{{/furiganaPlain}} + {{~furiganaPlain .~}} + {{furiganaPlain "読む" "よむ"}} ``` Output: diff --git a/ext/data/templates/anki-field-templates-upgrade-v21.handlebars b/ext/data/templates/anki-field-templates-upgrade-v21.handlebars index e69de29b..92034995 100644 --- a/ext/data/templates/anki-field-templates-upgrade-v21.handlebars +++ b/ext/data/templates/anki-field-templates-upgrade-v21.handlebars @@ -0,0 +1,30 @@ + +{{<<<<<<<}} +{{~#furigana}}{{{.}}}{{/furigana~}} +{{=======}} +{{~furigana .~}} +{{>>>>>>>}} + +{{<<<<<<<}} +{{#furigana}}{{{definition}}}{{/furigana}} +{{=======}} +{{furigana definition}} +{{>>>>>>>}} + +{{<<<<<<<}} +{{~#furiganaPlain}}{{{.}}}{{/furiganaPlain~}} +{{=======}} +{{~furiganaPlain .~}} +{{>>>>>>>}} + +{{<<<<<<<}} +{{#furiganaPlain}}{{{definition}}}{{/furiganaPlain}} +{{=======}} +{{furiganaPlain definition}} +{{>>>>>>>}} + +{{<<<<<<<}} +{{~#furigana expression reading~}}{{~/furigana~}} +{{=======}} +{{~furigana expression reading~}} +{{>>>>>>>}} diff --git a/ext/data/templates/default-anki-field-templates.handlebars b/ext/data/templates/default-anki-field-templates.handlebars index 31d5d13f..751236f4 100644 --- a/ext/data/templates/default-anki-field-templates.handlebars +++ b/ext/data/templates/default-anki-field-templates.handlebars @@ -78,22 +78,22 @@ {{#*inline "furigana"}} {{~#if merge~}} {{~#each definition.expressions~}} - {{~#furigana}}{{{.}}}{{/furigana~}} + {{~furigana .~}} {{~#unless @last}}、{{/unless~}} {{~/each~}} {{~else~}} - {{#furigana}}{{{definition}}}{{/furigana}} + {{furigana definition}} {{~/if~}} {{/inline}} {{#*inline "furigana-plain"}} {{~#if merge~}} {{~#each definition.expressions~}} - {{~#furiganaPlain}}{{{.}}}{{/furiganaPlain~}} + {{~furiganaPlain .~}} {{~#unless @last}}、{{/unless~}} {{~/each~}} {{~else~}} - {{#furiganaPlain}}{{{definition}}}{{/furiganaPlain}} + {{furiganaPlain definition}} {{~/if~}} {{/inline}} @@ -255,7 +255,7 @@
  • {{~#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~}} diff --git a/ext/js/templates/sandbox/anki-template-renderer.js b/ext/js/templates/sandbox/anki-template-renderer.js index 9e0bc8ed..e15bf895 100644 --- a/ext/js/templates/sandbox/anki-template-renderer.js +++ b/ext/js/templates/sandbox/anki-template-renderer.js @@ -132,6 +132,10 @@ class AnkiTemplateRenderer { return Handlebars.Utils.escapeExpression(text); } + _safeString(text) { + return new Handlebars.SafeString(text); + } + // Template helpers _dumpObject(context, object) { @@ -145,14 +149,16 @@ class AnkiTemplateRenderer { let result = ''; for (const {text, reading: reading2} of segs) { - if (reading2.length > 0) { - result += `${text}${reading2}`; + const safeText = this._escape(text); + const safeReading = this._escape(reading2); + if (safeReading.length > 0) { + result += `${safeText}${safeReading}`; } else { - result += text; + result += safeText; } } - return result; + return this._safeString(result); } _furiganaPlain(context, ...args) { @@ -173,12 +179,13 @@ 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; } } diff --git a/test/test-options-util.js b/test/test-options-util.js index 068367a2..e9504b0d 100644 --- a/test/test-options-util.js +++ b/test/test-options-util.js @@ -1217,14 +1217,92 @@ async function testFieldTemplatesUpdate(extDir) { <<>> {{~> (lookup . "marker") ~}}`.trimStart() }, - // block helper update + // block helper update: furigana and furiganaPlain { oldVersion: 20, newVersion: 21, old: ` +{{#*inline "furigana"}} + {{~#if merge~}} + {{~#each definition.expressions~}} + {{~#furigana}}{{{.}}}{{/furigana~}} + {{~#unless @last}}、{{/unless~}} + {{~/each~}} + {{~else~}} + {{#furigana}}{{{definition}}}{{/furigana}} + {{~/if~}} +{{/inline}} + +{{#*inline "furigana-plain"}} + {{~#if merge~}} + {{~#each definition.expressions~}} + {{~#furiganaPlain}}{{{.}}}{{/furiganaPlain~}} + {{~#unless @last}}、{{/unless~}} + {{~/each~}} + {{~else~}} + {{#furiganaPlain}}{{{definition}}}{{/furiganaPlain}} + {{~/if~}} +{{/inline}} + +{{#*inline "frequencies"}} + {{~#if (op ">" definition.frequencies.length 0)~}} +
      + {{~#each definition.frequencies~}} +
    • + {{~#if (op "!==" ../definition.type "kanji")~}} + {{~#if (op "||" (op ">" ../uniqueExpressions.length 1) (op ">" ../uniqueReadings.length 1))~}}( + {{~#furigana expression reading~}}{{~/furigana~}} + ) {{/if~}} + {{~/if~}} + {{~dictionary}}: {{frequency~}} +
    • + {{~/each~}} +
    + {{~/if~}} +{{/inline}} + {{~> (lookup . "marker") ~}}`.trimStart(), expected: ` +{{#*inline "furigana"}} + {{~#if merge~}} + {{~#each definition.expressions~}} + {{~furigana .~}} + {{~#unless @last}}、{{/unless~}} + {{~/each~}} + {{~else~}} + {{furigana definition}} + {{~/if~}} +{{/inline}} + +{{#*inline "furigana-plain"}} + {{~#if merge~}} + {{~#each definition.expressions~}} + {{~furiganaPlain .~}} + {{~#unless @last}}、{{/unless~}} + {{~/each~}} + {{~else~}} + {{furiganaPlain definition}} + {{~/if~}} +{{/inline}} + +{{#*inline "frequencies"}} + {{~#if (op ">" definition.frequencies.length 0)~}} +
      + {{~#each definition.frequencies~}} +
    • + {{~#if (op "!==" ../definition.type "kanji")~}} + {{~#if (op "||" (op ">" ../uniqueExpressions.length 1) (op ">" ../uniqueReadings.length 1))~}}( + {{~furigana expression reading~}} + ) {{/if~}} + {{~/if~}} + {{~dictionary}}: {{frequency~}} +
    • + {{~/each~}} +
    + {{~/if~}} +{{/inline}} + {{~> (lookup . "marker") ~}}`.trimStart() } ]; -- cgit v1.2.3 From 376a1b096874e601296321fa6307836e2736a05c Mon Sep 17 00:00:00 2001 From: praschke Date: Tue, 17 Oct 2023 21:52:31 +0100 Subject: fix: formatGlossary --- docs/templates.md | 4 +- .../anki-field-templates-upgrade-v21.handlebars | 18 ++++++ .../default-anki-field-templates.handlebars | 6 +- ext/js/templates/sandbox/anki-template-renderer.js | 5 +- test/test-options-util.js | 74 ++++++++++++++++++++++ 5 files changed, 99 insertions(+), 8 deletions(-) diff --git a/docs/templates.md b/docs/templates.md index bf5bd897..ce1e8d7e 100644 --- a/docs/templates.md +++ b/docs/templates.md @@ -657,7 +657,7 @@ structured-content generation.
    Syntax: - {{#formatGlossary dictionary}}{{{definitionEntry}}}{{/pitchCategories}}
    + {{formatGlossary dictionary definitionEntry}}
    * _`dictionary`_
    The dictionary that the glossary entry belongs to. @@ -668,7 +668,7 @@ structured-content generation. Example: ```handlebars - {{#each glossary}}{{#formatGlossary ../dictionary}}{{{.}}}{{/formatGlossary}}{{/each}} + {{#each glossary}}{{formatGlossary ../dictionary .}}{{/each}} ``` Output: diff --git a/ext/data/templates/anki-field-templates-upgrade-v21.handlebars b/ext/data/templates/anki-field-templates-upgrade-v21.handlebars index 92034995..99db50b6 100644 --- a/ext/data/templates/anki-field-templates-upgrade-v21.handlebars +++ b/ext/data/templates/anki-field-templates-upgrade-v21.handlebars @@ -1,4 +1,22 @@ +{{<<<<<<<}} +{{#each glossary}}{{#formatGlossary ../dictionary}}{{{.}}}{{/formatGlossary}}{{/each}} +{{=======}} +{{#each glossary}}{{formatGlossary ../dictionary .}}{{/each}} +{{>>>>>>>}} + +{{<<<<<<<}} +{{#each glossary}}{{#formatGlossary ../dictionary}}{{{.}}}{{/formatGlossary}}{{#unless @last}} | {{/unless}}{{/each}} +{{=======}} +{{#each glossary}}{{formatGlossary ../dictionary .}}{{#unless @last}} | {{/unless}}{{/each}} +{{>>>>>>>}} + +{{<<<<<<<}} +
      {{#each glossary}}
    • {{#formatGlossary ../dictionary}}{{{.}}}{{/formatGlossary}}
    • {{/each}}
    +{{=======}} +
      {{#each glossary}}
    • {{formatGlossary ../dictionary .}}
    • {{/each}}
    +{{>>>>>>>}} + {{<<<<<<<}} {{~#furigana}}{{{.}}}{{/furigana~}} {{=======}} diff --git a/ext/data/templates/default-anki-field-templates.handlebars b/ext/data/templates/default-anki-field-templates.handlebars index 751236f4..58bc68e2 100644 --- a/ext/data/templates/default-anki-field-templates.handlebars +++ b/ext/data/templates/default-anki-field-templates.handlebars @@ -21,11 +21,11 @@ {{~#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~}} -
      {{#each glossary}}
    • {{#formatGlossary ../dictionary}}{{{.}}}{{/formatGlossary}}
    • {{/each}}
    +
      {{#each glossary}}
    • {{formatGlossary ../dictionary .}}
    • {{/each}}
    {{~/if~}} {{~#set "previousDictionary" dictionary~}}{{~/set~}} {{/inline}} diff --git a/ext/js/templates/sandbox/anki-template-renderer.js b/ext/js/templates/sandbox/anki-template-renderer.js index e15bf895..62bf71b8 100644 --- a/ext/js/templates/sandbox/anki-template-renderer.js +++ b/ext/js/templates/sandbox/anki-template-renderer.js @@ -497,7 +497,7 @@ class AnkiTemplateRenderer { this._normalizeHtml(container, styleApplier, datasetKeyIgnorePattern); const result = container.innerHTML; container.textContent = ''; - return result; + return this._safeString(result); } _normalizeHtml(root, styleApplier, datasetKeyIgnorePattern) { @@ -550,9 +550,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/test/test-options-util.js b/test/test-options-util.js index e9504b0d..c2780650 100644 --- a/test/test-options-util.js +++ b/test/test-options-util.js @@ -1303,6 +1303,80 @@ async function testFieldTemplatesUpdate(extDir) { {{~/if~}} {{/inline}} +{{~> (lookup . "marker") ~}}`.trimStart() + }, + // block helper update: formatGlossary + { + oldVersion: 20, + newVersion: 21, + old: ` +{{#*inline "glossary-single"}} + {{~#unless brief~}} + {{~#scope~}} + {{~#set "any" false}}{{/set~}} + {{~#each definitionTags~}} + {{~#if (op "||" (op "!" @root.compactTags) (op "!" redundant))~}} + {{~#if (get "any")}}, {{else}}({{/if~}} + {{name}} + {{~#set "any" true}}{{/set~}} + {{~/if~}} + {{~/each~}} + {{~#unless noDictionaryTag~}} + {{~#if (op "||" (op "!" @root.compactTags) (op "!==" dictionary (get "previousDictionary")))~}} + {{~#if (get "any")}}, {{else}}({{/if~}} + {{dictionary}} + {{~#set "any" true}}{{/set~}} + {{~/if~}} + {{~/unless~}} + {{~#if (get "any")}}) {{/if~}} + {{~/scope~}} + {{~#if only~}}({{#each only}}{{.}}{{#unless @last}}, {{/unless}}{{/each}} only) {{/if~}} + {{~/unless~}} + {{~#if (op "<=" glossary.length 1)~}} + {{#each glossary}}{{#formatGlossary ../dictionary}}{{{.}}}{{/formatGlossary}}{{/each}} + {{~else if @root.compactGlossaries~}} + {{#each glossary}}{{#formatGlossary ../dictionary}}{{{.}}}{{/formatGlossary}}{{#unless @last}} | {{/unless}}{{/each}} + {{~else~}} +
      {{#each glossary}}
    • {{#formatGlossary ../dictionary}}{{{.}}}{{/formatGlossary}}
    • {{/each}}
    + {{~/if~}} + {{~#set "previousDictionary" dictionary~}}{{~/set~}} +{{/inline}} + +{{~> (lookup . "marker") ~}}`.trimStart(), + + expected: ` +{{#*inline "glossary-single"}} + {{~#unless brief~}} + {{~#scope~}} + {{~#set "any" false}}{{/set~}} + {{~#each definitionTags~}} + {{~#if (op "||" (op "!" @root.compactTags) (op "!" redundant))~}} + {{~#if (get "any")}}, {{else}}({{/if~}} + {{name}} + {{~#set "any" true}}{{/set~}} + {{~/if~}} + {{~/each~}} + {{~#unless noDictionaryTag~}} + {{~#if (op "||" (op "!" @root.compactTags) (op "!==" dictionary (get "previousDictionary")))~}} + {{~#if (get "any")}}, {{else}}({{/if~}} + {{dictionary}} + {{~#set "any" true}}{{/set~}} + {{~/if~}} + {{~/unless~}} + {{~#if (get "any")}}) {{/if~}} + {{~/scope~}} + {{~#if only~}}({{#each only}}{{.}}{{#unless @last}}, {{/unless}}{{/each}} only) {{/if~}} + {{~/unless~}} + {{~#if (op "<=" glossary.length 1)~}} + {{#each glossary}}{{formatGlossary ../dictionary .}}{{/each}} + {{~else if @root.compactGlossaries~}} + {{#each glossary}}{{formatGlossary ../dictionary .}}{{#unless @last}} | {{/unless}}{{/each}} + {{~else~}} +
      {{#each glossary}}
    • {{formatGlossary ../dictionary .}}
    • {{/each}}
    + {{~/if~}} + {{~#set "previousDictionary" dictionary~}}{{~/set~}} +{{/inline}} + {{~> (lookup . "marker") ~}}`.trimStart() } ]; -- cgit v1.2.3 From 68ff30006edcd0dca44326780d34a6ca39f65157 Mon Sep 17 00:00:00 2001 From: praschke Date: Tue, 17 Oct 2023 21:54:53 +0100 Subject: fix: regexReplace and regexMatch joining the args together without cutting out the options arg can add an '[object Object]' into the result. --- docs/templates.md | 4 ++-- ext/js/templates/sandbox/anki-template-renderer.js | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/docs/templates.md b/docs/templates.md index ce1e8d7e..e0ea0861 100644 --- a/docs/templates.md +++ b/docs/templates.md @@ -147,7 +147,7 @@ Uses a [regular expression](https://developer.mozilla.org/en-US/docs/Web/JavaScr Syntax: {{#regexReplace regex replacement [flags]}}text-to-modify{{/regexReplace}}
    - {{#regexReplace regex replacement [flags] [text-to-modify]...}}{{/regexReplace}}
    + {{regexReplace regex replacement [flags] [text-to-modify]...}}
    * _`regex`_
    The raw string used to create the regular expression. This value is passed to the [`RegExp`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/RegExp/RegExp) constructor. @@ -181,7 +181,7 @@ Uses a [regular expression](https://developer.mozilla.org/en-US/docs/Web/JavaScr Syntax: {{#regexMatch regex [flags]}}text-to-modify{{/regexMatch}}
    - {{#regexMatch regex [flags] [text-to-modify]...}}{{/regexMatch}}
    + {{regexMatch regex [flags] [text-to-modify]...}}
    * _`regex`_
    The raw string used to create the regular expression. This value is passed to the [`RegExp`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/RegExp/RegExp) constructor. diff --git a/ext/js/templates/sandbox/anki-template-renderer.js b/ext/js/templates/sandbox/anki-template-renderer.js index 62bf71b8..5d8ebd38 100644 --- a/ext/js/templates/sandbox/anki-template-renderer.js +++ b/ext/js/templates/sandbox/anki-template-renderer.js @@ -226,7 +226,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 { @@ -250,7 +250,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 { -- cgit v1.2.3 From 9f8269606fdf51765f6d13de4caac709691b0fea Mon Sep 17 00:00:00 2001 From: praschke Date: Tue, 17 Oct 2023 22:11:29 +0100 Subject: update: set and get --- docs/templates.md | 20 ++-- .../anki-field-templates-upgrade-v21.handlebars | 61 ++++++++++++ .../default-anki-field-templates.handlebars | 24 ++--- test/test-options-util.js | 110 ++++++++++++++++++++- 4 files changed, 189 insertions(+), 26 deletions(-) diff --git a/docs/templates.md b/docs/templates.md index e0ea0861..e19309a7 100644 --- a/docs/templates.md +++ b/docs/templates.md @@ -351,7 +351,7 @@ Gets a value from the custom state stack.
    Syntax: - {{#get name}}{{/get}} + {{get name}} * _`name`_
    The name of the variable to get. @@ -360,7 +360,7 @@ Gets a value from the custom state stack. Example: ```handlebars - {{#get "some-text"}}{{/get}} + {{get "some-text"}} ``` Output: @@ -378,7 +378,7 @@ Assigns a value to the custom state stack. Syntax: {{#set name}}value{{/get}}
    - {{#set name value}}{{/get}}
    + {{set name value}}
    * _`name`_
    The name of the variable to assign. @@ -390,7 +390,7 @@ Assigns a value to the custom state stack. ```handlebars {{#set "some-text"}}This is the value of some-text!{{/set~}} - {{~#set "some-number" 32}}{{/set}} + {{~set "some-number" 32}} ``` Output: @@ -419,14 +419,14 @@ and variable lookups will start from the most recent scope and work backwards un Example: ```handlebars - {{~#set "key" 32}}{{/set~}} - {{~#get "key"}}{{/get~}}, + {{~set "key" 32~}} + {{~get "key"~}}, {{~#scope~}} - {{~#get "key"}}{{/get~}}, - {{~#set "key" 64}}{{/set~}} - {{~#get "key"}}{{/get~}}, + {{~#get "key"~}}, + {{~#set "key" 64~}} + {{~#get "key"~}}, {{~/scope~}} - {{~#get "key"}}{{/get~}} + {{~get "key"~}} ``` Output: diff --git a/ext/data/templates/anki-field-templates-upgrade-v21.handlebars b/ext/data/templates/anki-field-templates-upgrade-v21.handlebars index 99db50b6..2fa0f0aa 100644 --- a/ext/data/templates/anki-field-templates-upgrade-v21.handlebars +++ b/ext/data/templates/anki-field-templates-upgrade-v21.handlebars @@ -1,3 +1,14 @@ +{{<<<<<<<}} +{{~#set "any" false}}{{/set~}} +{{=======}} +{{~set "any" false~}} +{{>>>>>>>}} + +{{<<<<<<<}} +{{~#set "any" true}}{{/set~}} +{{=======}} +{{~set "any" true~}} +{{>>>>>>>}} {{<<<<<<<}} {{#each glossary}}{{#formatGlossary ../dictionary}}{{{.}}}{{/formatGlossary}}{{/each}} @@ -17,6 +28,12 @@
      {{#each glossary}}
    • {{formatGlossary ../dictionary .}}
    • {{/each}}
    {{>>>>>>>}} +{{<<<<<<<}} +{{~#set "previousDictionary" dictionary~}}{{~/set~}} +{{=======}} +{{~set "previousDictionary" dictionary~}} +{{>>>>>>>}} + {{<<<<<<<}} {{~#furigana}}{{{.}}}{{/furigana~}} {{=======}} @@ -46,3 +63,47 @@ {{=======}} {{~furigana expression reading~}} {{>>>>>>>}} + +{{<<<<<<<}} +{{~#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 (concat "used_" .) true~}}{{~/set~}} + {{~#set "first" false~}}{{~/set~}} +{{=======}} + {{~set (concat "used_" .) true~}} + {{~set "first" false~}} +{{>>>>>>>}} diff --git a/ext/data/templates/default-anki-field-templates.handlebars b/ext/data/templates/default-anki-field-templates.handlebars index 58bc68e2..69c7e7a1 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}}({{/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}}({{/if~}} {{dictionary}} - {{~#set "any" true}}{{/set~}} + {{~set "any" true~}} {{~/if~}} {{~/unless~}} {{~#if (get "any")}}) {{/if~}} @@ -27,7 +27,7 @@ {{~else~}}
      {{#each glossary}}
    • {{formatGlossary ../dictionary .}}
    • {{/each}}
    {{~/if~}} - {{~#set "previousDictionary" dictionary~}}{{~/set~}} + {{~set "previousDictionary" dictionary~}} {{/inline}} {{#*inline "audio"}} @@ -189,11 +189,11 @@ {{#*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" ""~}} ({{#each (get "exclusive")~}} - {{~#get "separator"}}{{/get~}}{{{.}}} + {{~get "separator"~}}{{{.}}} {{~/each}} only) {{~/if~}} {{~/scope~}} @@ -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~}} diff --git a/test/test-options-util.js b/test/test-options-util.js index c2780650..78204de9 100644 --- a/test/test-options-util.js +++ b/test/test-options-util.js @@ -1348,19 +1348,19 @@ async function testFieldTemplatesUpdate(extDir) { {{#*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}}({{/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}}({{/if~}} {{dictionary}} - {{~#set "any" true}}{{/set~}} + {{~set "any" true~}} {{~/if~}} {{~/unless~}} {{~#if (get "any")}}) {{/if~}} @@ -1374,7 +1374,109 @@ async function testFieldTemplatesUpdate(extDir) { {{~else~}}
      {{#each glossary}}
    • {{formatGlossary ../dictionary .}}
    • {{/each}}
    {{~/if~}} - {{~#set "previousDictionary" dictionary~}}{{~/set~}} + {{~set "previousDictionary" dictionary~}} +{{/inline}} + +{{~> (lookup . "marker") ~}}`.trimStart() + }, + // block helper update: set and get + { + oldVersion: 20, + newVersion: 21, + old: ` +{{#*inline "pitch-accent-item-disambiguation"}} + {{~#scope~}} + {{~#set "exclusive" (spread exclusiveExpressions exclusiveReadings)}}{{/set~}} + {{~#if (op ">" (property (get "exclusive") "length") 0)~}} + {{~#set "separator" ""~}}{{/set~}} + ({{#each (get "exclusive")~}} + {{~#get "separator"}}{{/get~}}{{{.}}} + {{~/each}} only) + {{~/if~}} + {{~/scope~}} +{{/inline}} + +{{#*inline "stroke-count"}} + {{~#scope~}} + {{~#set "found" false}}{{/set~}} + {{~#each definition.stats.misc~}} + {{~#if (op "===" name "strokes")~}} + {{~#set "found" true}}{{/set~}} + Stroke count: {{value}} + {{~/if~}} + {{~/each~}} + {{~#if (op "!" (get "found"))~}} + Stroke count: Unknown + {{~/if~}} + {{~/scope~}} +{{/inline}} + +{{#*inline "part-of-speech"}} + {{~#scope~}} + {{~#if (op "!==" definition.type "kanji")~}} + {{~#set "first" true}}{{/set~}} + {{~#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~}} + {{~/unless~}} + {{~/each~}} + {{~/each~}} + {{~#if (get "first")~}}Unknown{{~/if~}} + {{~/if~}} + {{~/scope~}} +{{/inline}} + +{{~> (lookup . "marker") ~}}`.trimStart(), + + expected: ` +{{#*inline "pitch-accent-item-disambiguation"}} + {{~#scope~}} + {{~set "exclusive" (spread exclusiveExpressions exclusiveReadings)~}} + {{~#if (op ">" (property (get "exclusive") "length") 0)~}} + {{~set "separator" ""~}} + ({{#each (get "exclusive")~}} + {{~get "separator"~}}{{{.}}} + {{~/each}} only) + {{~/if~}} + {{~/scope~}} +{{/inline}} + +{{#*inline "stroke-count"}} + {{~#scope~}} + {{~set "found" false~}} + {{~#each definition.stats.misc~}} + {{~#if (op "===" name "strokes")~}} + {{~set "found" true~}} + Stroke count: {{value}} + {{~/if~}} + {{~/each~}} + {{~#if (op "!" (get "found"))~}} + Stroke count: Unknown + {{~/if~}} + {{~/scope~}} +{{/inline}} + +{{#*inline "part-of-speech"}} + {{~#scope~}} + {{~#if (op "!==" definition.type "kanji")~}} + {{~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 "first" false~}} + {{~/unless~}} + {{~/each~}} + {{~/each~}} + {{~#if (get "first")~}}Unknown{{~/if~}} + {{~/if~}} + {{~/scope~}} {{/inline}} {{~> (lookup . "marker") ~}}`.trimStart() -- cgit v1.2.3 From 9b798601b48a40b65e38b433924a99d155872ba7 Mon Sep 17 00:00:00 2001 From: praschke Date: Tue, 17 Oct 2023 22:25:30 +0100 Subject: update: hasMedia and getMedia --- docs/templates.md | 18 ++--- .../anki-field-templates-upgrade-v21.handlebars | 36 ++++++++++ .../default-anki-field-templates.handlebars | 12 ++-- test/test-options-util.js | 82 ++++++++++++++++++++++ 4 files changed, 133 insertions(+), 15 deletions(-) diff --git a/docs/templates.md b/docs/templates.md index e19309a7..0aa26b84 100644 --- a/docs/templates.md +++ b/docs/templates.md @@ -686,8 +686,8 @@ These functions are used together in order to request media and other types of o
    Syntax: - {{#hasMedia type args...}}{{/hasMedia}}
    - {{#getMedia type args... [escape=true|false]}}{{/getMedia}}
    + {{hasMedia type args...}}
    + {{getMedia type args... [escape=true|false]}}
    * _`type`_
    The type of media to check for. @@ -710,19 +710,19 @@ These functions are used together in order to request media and other types of o Examples: ```handlebars - {{#if (hasMedia "audio")}}The audio file name is: {{#getMedia "audio"}}{{/getMedia}}{{/if}} + {{#if (hasMedia "audio")}}The audio file name is: {{getMedia "audio"}}{{/if}} - {{#if (hasMedia "screenshot")}}The screenshot file name is: {{#getMedia "screenshot"}}{{/getMedia}}{{/if}} + {{#if (hasMedia "screenshot")}}The screenshot file name is: {{getMedia "screenshot"}}{{/if}} - {{#if (hasMedia "clipboardImage")}}The clipboard image file name is: {{#getMedia "clipboardImage"}}{{/getMedia}}{{/if}} + {{#if (hasMedia "clipboardImage")}}The clipboard image file name is: {{getMedia "clipboardImage"}}{{/if}} - {{#if (hasMedia "clipboardText")}}The clipboard text is: {{#getMedia "clipboardText"}}{{/getMedia}}{{/if}} + {{#if (hasMedia "clipboardText")}}The clipboard text is: {{getMedia "clipboardText"}}{{/if}} - {{#if (hasMedia "selectionText")}}The selection text is: {{#getMedia "selectionText"}}{{/getMedia}}{{/if}} + {{#if (hasMedia "selectionText")}}The selection text is: {{getMedia "selectionText"}}{{/if}} - {{#if (hasMedia "textFurigana" "日本語")}}This is an example of text with generated furigana: {{#getMedia "textFurigana" "日本語" escape=false}}{{/getMedia}}{{/if}} + {{#if (hasMedia "textFurigana" "日本語")}}This is an example of text with generated furigana: {{getMedia "textFurigana" "日本語" escape=false}}{{/if}} - {{#if (hasMedia "dictionaryMedia" "image.png" dictionary="Example Dictionary")}}The remapped file name for image.png is: {{#getMedia "dictionaryMedia" "image.png" dictionary="Example Dictionary"}}{{/getMedia}}{{/if}} + {{#if (hasMedia "dictionaryMedia" "image.png" dictionary="Example Dictionary")}}The remapped file name for image.png is: {{getMedia "dictionaryMedia" "image.png" dictionary="Example Dictionary"}}{{/if}} ``` Output: diff --git a/ext/data/templates/anki-field-templates-upgrade-v21.handlebars b/ext/data/templates/anki-field-templates-upgrade-v21.handlebars index 2fa0f0aa..0bfd95a5 100644 --- a/ext/data/templates/anki-field-templates-upgrade-v21.handlebars +++ b/ext/data/templates/anki-field-templates-upgrade-v21.handlebars @@ -34,6 +34,12 @@ {{~set "previousDictionary" dictionary~}} {{>>>>>>>}} +{{<<<<<<<}} +[sound:{{#getMedia "audio"}}{{/getMedia}}] +{{=======}} +[sound:{{getMedia "audio"}}] +{{>>>>>>>}} + {{<<<<<<<}} {{~#furigana}}{{{.}}}{{/furigana~}} {{=======}} @@ -58,6 +64,24 @@ {{furiganaPlain definition}} {{>>>>>>>}} +{{<<<<<<<}} + +{{=======}} + +{{>>>>>>>}} + +{{<<<<<<<}} + +{{=======}} + +{{>>>>>>>}} + +{{<<<<<<<}} +{{~#if (hasMedia "clipboardText")}}{{#getMedia "clipboardText"}}{{/getMedia}}{{/if~}} +{{=======}} +{{~#if (hasMedia "clipboardText")}}{{getMedia "clipboardText"}}{{/if~}} +{{>>>>>>>}} + {{<<<<<<<}} {{~#furigana expression reading~}}{{~/furigana~}} {{=======}} @@ -107,3 +131,15 @@ {{~set (concat "used_" .) true~}} {{~set "first" false~}} {{>>>>>>>}} + +{{<<<<<<<}} +{{~#if (hasMedia "selectionText")}}{{#getMedia "selectionText"}}{{/getMedia}}{{/if~}} +{{=======}} +{{~#if (hasMedia "selectionText")}}{{getMedia "selectionText"}}{{/if~}} +{{>>>>>>>}} + +{{<<<<<<<}} +{{#getMedia "textFurigana" definition.cloze.sentence escape=false}}{{/getMedia}} +{{=======}} +{{getMedia "textFurigana" definition.cloze.sentence escape=false}} +{{>>>>>>>}} diff --git a/ext/data/templates/default-anki-field-templates.handlebars b/ext/data/templates/default-anki-field-templates.handlebars index 69c7e7a1..08950f78 100644 --- a/ext/data/templates/default-anki-field-templates.handlebars +++ b/ext/data/templates/default-anki-field-templates.handlebars @@ -32,7 +32,7 @@ {{#*inline "audio"}} {{~#if (hasMedia "audio")~}} - [sound:{{#getMedia "audio"}}{{/getMedia}}] + [sound:{{getMedia "audio"}}] {{~/if~}} {{/inline}} @@ -174,7 +174,7 @@ {{#*inline "screenshot"}} {{~#if (hasMedia "screenshot")~}} - + {{~/if~}} {{/inline}} @@ -231,12 +231,12 @@ {{#*inline "clipboard-image"}} {{~#if (hasMedia "clipboardImage")~}} - + {{~/if~}} {{/inline}} {{#*inline "clipboard-text"}} - {{~#if (hasMedia "clipboardText")}}{{#getMedia "clipboardText"}}{{/getMedia}}{{/if~}} + {{~#if (hasMedia "clipboardText")}}{{getMedia "clipboardText"}}{{/if~}} {{/inline}} {{#*inline "conjugation"}} @@ -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/test/test-options-util.js b/test/test-options-util.js index 78204de9..23cfc121 100644 --- a/test/test-options-util.js +++ b/test/test-options-util.js @@ -1479,6 +1479,88 @@ async function testFieldTemplatesUpdate(extDir) { {{~/scope~}} {{/inline}} +{{~> (lookup . "marker") ~}}`.trimStart() + }, + // block helper update: hasMedia and getMedia + { + oldVersion: 20, + newVersion: 21, + old: ` +{{#*inline "audio"}} + {{~#if (hasMedia "audio")~}} + [sound:{{#getMedia "audio"}}{{/getMedia}}] + {{~/if~}} +{{/inline}} + +{{#*inline "screenshot"}} + {{~#if (hasMedia "screenshot")~}} + + {{~/if~}} +{{/inline}} + +{{#*inline "clipboard-image"}} + {{~#if (hasMedia "clipboardImage")~}} + + {{~/if~}} +{{/inline}} + +{{#*inline "clipboard-text"}} + {{~#if (hasMedia "clipboardText")}}{{#getMedia "clipboardText"}}{{/getMedia}}{{/if~}} +{{/inline}} + +{{#*inline "selection-text"}} + {{~#if (hasMedia "selectionText")}}{{#getMedia "selectionText"}}{{/getMedia}}{{/if~}} +{{/inline}} + +{{#*inline "sentence-furigana"}} + {{~#if definition.cloze~}} + {{~#if (hasMedia "textFurigana" definition.cloze.sentence)~}} + {{#getMedia "textFurigana" definition.cloze.sentence escape=false}}{{/getMedia}} + {{~else~}} + {{definition.cloze.sentence}} + {{~/if~}} + {{~/if~}} +{{/inline}} + +{{~> (lookup . "marker") ~}}`.trimStart(), + + expected: ` +{{#*inline "audio"}} + {{~#if (hasMedia "audio")~}} + [sound:{{getMedia "audio"}}] + {{~/if~}} +{{/inline}} + +{{#*inline "screenshot"}} + {{~#if (hasMedia "screenshot")~}} + + {{~/if~}} +{{/inline}} + +{{#*inline "clipboard-image"}} + {{~#if (hasMedia "clipboardImage")~}} + + {{~/if~}} +{{/inline}} + +{{#*inline "clipboard-text"}} + {{~#if (hasMedia "clipboardText")}}{{getMedia "clipboardText"}}{{/if~}} +{{/inline}} + +{{#*inline "selection-text"}} + {{~#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}} + {{~else~}} + {{definition.cloze.sentence}} + {{~/if~}} + {{~/if~}} +{{/inline}} + {{~> (lookup . "marker") ~}}`.trimStart() } ]; -- cgit v1.2.3 From 4527cc03fe88cd747d0eb62a65d9d54247653483 Mon Sep 17 00:00:00 2001 From: praschke Date: Tue, 17 Oct 2023 22:35:34 +0100 Subject: update: pronunciation --- docs/templates.md | 4 ++-- .../anki-field-templates-upgrade-v21.handlebars | 6 ++++++ .../templates/default-anki-field-templates.handlebars | 2 +- test/test-options-util.js | 18 ++++++++++++++++++ 4 files changed, 27 insertions(+), 3 deletions(-) diff --git a/docs/templates.md b/docs/templates.md index 0aa26b84..f021dea6 100644 --- a/docs/templates.md +++ b/docs/templates.md @@ -754,7 +754,7 @@ same as the system used for generating popup and search page dictionary entries.
    Syntax: - {{#pronunciation format=string reading=string downstepPosition=integer [nasalPositions=array] [devoicePositions=array]}}{{/pronunciation}}
    + {{pronunciation format=string reading=string downstepPosition=integer [nasalPositions=array] [devoicePositions=array]}}
    * _`format`_
    The format of the HTML to generate. This can be any of the following values: @@ -774,7 +774,7 @@ same as the system used for generating popup and search page dictionary entries. Example: ```handlebars - {{~#pronunciation format='text' reading='よむ' downstepPosition=1~}}{{~/pronunciation~}} + {{~pronunciation format='text' reading='よむ' downstepPosition=1~}} ```
    diff --git a/ext/data/templates/anki-field-templates-upgrade-v21.handlebars b/ext/data/templates/anki-field-templates-upgrade-v21.handlebars index 0bfd95a5..4d88b812 100644 --- a/ext/data/templates/anki-field-templates-upgrade-v21.handlebars +++ b/ext/data/templates/anki-field-templates-upgrade-v21.handlebars @@ -82,6 +82,12 @@ {{~#if (hasMedia "clipboardText")}}{{getMedia "clipboardText"}}{{/if~}} {{>>>>>>>}} +{{<<<<<<<}} +{{~#pronunciation format=format reading=reading downstepPosition=position nasalPositions=nasalPositions devoicePositions=devoicePositions~}}{{~/pronunciation~}} +{{=======}} +{{~pronunciation format=format reading=reading downstepPosition=position nasalPositions=nasalPositions devoicePositions=devoicePositions~}} +{{>>>>>>>}} + {{<<<<<<<}} {{~#furigana expression reading~}}{{~/furigana~}} {{=======}} diff --git a/ext/data/templates/default-anki-field-templates.handlebars b/ext/data/templates/default-anki-field-templates.handlebars index 08950f78..d94f6d70 100644 --- a/ext/data/templates/default-anki-field-templates.handlebars +++ b/ext/data/templates/default-anki-field-templates.handlebars @@ -184,7 +184,7 @@ {{! 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"}} diff --git a/test/test-options-util.js b/test/test-options-util.js index 23cfc121..d94028c0 100644 --- a/test/test-options-util.js +++ b/test/test-options-util.js @@ -1561,6 +1561,24 @@ async function testFieldTemplatesUpdate(extDir) { {{~/if~}} {{/inline}} +{{~> (lookup . "marker") ~}}`.trimStart() + }, + // block helper update: pronunciation + { + oldVersion: 20, + newVersion: 21, + old: ` +{{#*inline "pitch-accent-item"}} + {{~#pronunciation format=format reading=reading downstepPosition=position nasalPositions=nasalPositions devoicePositions=devoicePositions~}}{{~/pronunciation~}} +{{/inline}} + +{{~> (lookup . "marker") ~}}`.trimStart(), + + expected: ` +{{#*inline "pitch-accent-item"}} + {{~pronunciation format=format reading=reading downstepPosition=position nasalPositions=nasalPositions devoicePositions=devoicePositions~}} +{{/inline}} + {{~> (lookup . "marker") ~}}`.trimStart() } ]; -- cgit v1.2.3 From a454cc3ca1c34e51de13fe21f375f1f47d96a1e9 Mon Sep 17 00:00:00 2001 From: praschke Date: Mon, 16 Oct 2023 23:02:41 +0100 Subject: remove kanjiLinks and sanitizeCssClass --- docs/templates.md | 57 ---------------------- ext/js/templates/sandbox/anki-template-renderer.js | 20 -------- 2 files changed, 77 deletions(-) diff --git a/docs/templates.md b/docs/templates.md index f021dea6..86c60db9 100644 --- a/docs/templates.md +++ b/docs/templates.md @@ -842,60 +842,3 @@ Converts hiragana text to katakana. ヨミチャン ヨミチャン ヨミチャン ```
    - - -## Legacy Helpers - -Yomichan has historically used Handlebars templates to generate the HTML used on the search page and results popup. -To simplify the and improve Yomichan's capabilities, the HTML elements are now generated directly using a different process. - -As such, there are several leftover Handlebars helpers that do not have much utility for Anki templates, but are kept for compatibility purposes. - - -### `kanjiLinks` - -Replaces kanji characters in the text with linkified versions. - -
    - Syntax: - - {{#kanjiLinks}}text{{/kanjiLinks}} -
    -
    - Example: - - ```handlebars - {{#kanjiLinks}}読む{{/kanjiLinks}} - ``` - - Output: - ```html - む - ``` - - Preview: -
    -
    - - -### `sanitizeCssClass` - -Sanitizes text so it can be used as a CSS class name. - -
    - Syntax: - - {{#sanitizeCssClass}}text{{/sanitizeCssClass}} -
    -
    - Example: - - ```handlebars - {{#sanitizeCssClass}}some text with many types of characters !@#$%^ 読む{{/sanitizeCssClass}} - ``` - - Output: - ```html - some_text_with_many_types_of_characters________読む - ``` -
    diff --git a/ext/js/templates/sandbox/anki-template-renderer.js b/ext/js/templates/sandbox/anki-template-renderer.js index 5d8ebd38..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)], @@ -189,20 +187,6 @@ class AnkiTemplateRenderer { } } - _kanjiLinks(context, options) { - const jp = this._japaneseUtil; - let result = ''; - for (const c of options.fn(context)) { - if (jp.isCodePointKanji(c.codePointAt(0))) { - result += `${c}`; - } else { - result += c; - } - } - - return result; - } - _stringToMultiLineHtml(string) { return string.split('\n').join('
    '); } @@ -211,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}} -- cgit v1.2.3 From 60a3740af9c4dbf08181ae74b71d753b5ea133dd Mon Sep 17 00:00:00 2001 From: praschke Date: Mon, 16 Oct 2023 23:10:09 +0100 Subject: docs: mergeTags --- docs/templates.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/templates.md b/docs/templates.md index 86c60db9..6605012a 100644 --- a/docs/templates.md +++ b/docs/templates.md @@ -212,7 +212,7 @@ Creates a set of all unique tags for the definition and returns a text represent
    Syntax: - {{#mergeTags definition isGroupMode isMergeMode}}{{/mergeTags}} + {{mergeTags definition isGroupMode isMergeMode}} * _`definition`_
    The root definition object. @@ -225,7 +225,7 @@ Creates a set of all unique tags for the definition and returns a text represent Example: ```handlebars - {{~#mergeTags definition group merge}}{{/mergeTags~}} + {{~mergeTags definition group merge~}} ``` Output: -- cgit v1.2.3 From 383366bc064040e6b6323cce459019e0a147a636 Mon Sep 17 00:00:00 2001 From: praschke Date: Mon, 16 Oct 2023 23:13:43 +0100 Subject: docs: multiLine --- docs/templates.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/templates.md b/docs/templates.md index 6605012a..b7e75437 100644 --- a/docs/templates.md +++ b/docs/templates.md @@ -122,11 +122,11 @@ Replaces newline characters with a forced HTML line break `
    `. Example: ```handlebars - {{#kanjiLinks~}} + {{#multiLine~}} some multiline text - {{~/kanjiLinks}} + {{~/multiLine}} ``` Output: -- cgit v1.2.3 From f5145607ce2933fa9ae8cfb99e651a3dc3860fef Mon Sep 17 00:00:00 2001 From: praschke Date: Mon, 16 Oct 2023 23:14:15 +0100 Subject: docs: spread --- docs/templates.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/templates.md b/docs/templates.md index b7e75437..d27382fe 100644 --- a/docs/templates.md +++ b/docs/templates.md @@ -279,7 +279,7 @@ This allows it to be used similar to an [`Array.concat`](https://developer.mozil
    Syntax: - {{#spread iterable1 iterable2 ... iterableN}}{{/spread}} + {{spread iterable1 iterable2 ... iterableN}} * _`iterableN`_
    A variable amount of iterable objects to combine into a single array. -- cgit v1.2.3 From daf3c0f44434ad79f7bbcdc518368396d43b8cf1 Mon Sep 17 00:00:00 2001 From: praschke Date: Mon, 16 Oct 2023 23:15:43 +0100 Subject: docs: op --- docs/templates.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/templates.md b/docs/templates.md index d27382fe..c1ef23b7 100644 --- a/docs/templates.md +++ b/docs/templates.md @@ -331,7 +331,7 @@ If an unknown operator is specified, the `undefined` value is returned. ```handlebars {{#if (op "===" value1 value2)}}Values are equal{{/op~}}
    {{~#op "-" value1}}{{/op~}}
    - {{~#op "?:" value1 "a" "b"}}{{/op}} + {{~op "?:" value1 "a" "b"}} ``` Output: -- cgit v1.2.3 From 23a1ca60d65c0f896b954633792f2f4fc544a3d7 Mon Sep 17 00:00:00 2001 From: praschke Date: Mon, 16 Oct 2023 23:25:03 +0100 Subject: docs: property --- docs/templates.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/templates.md b/docs/templates.md index c1ef23b7..05a5247a 100644 --- a/docs/templates.md +++ b/docs/templates.md @@ -443,7 +443,7 @@ Repeatedly gets a property of an object.
    Syntax: - {{#property object property1 property2 ... propertyN}}{{/property}} + {{property object property1 property2 ... propertyN}} * _`object`_
    The initial object to use. -- cgit v1.2.3 From 881a7cd77d4894db490de274bf32119228137a21 Mon Sep 17 00:00:00 2001 From: praschke Date: Mon, 16 Oct 2023 23:26:35 +0100 Subject: docs: isMoraPitchHigh and getKanaMorae --- docs/templates.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/templates.md b/docs/templates.md index 05a5247a..b99702b3 100644 --- a/docs/templates.md +++ b/docs/templates.md @@ -494,7 +494,7 @@ Returns whether or not a mora will have a high pitch, given the index of the mor
    Syntax: - {{#isMoraPitchHigh index position}}{{/isMoraPitchHigh}} + {{isMoraPitchHigh index position}}
    Example: @@ -517,7 +517,7 @@ Returns an array of the mora for a kana string.
    Syntax: - {{#getKanaMorae kana-string}}{{/getKanaMorae}} + {{getKanaMorae kana-string}}
    Example: -- cgit v1.2.3 From feec5af726a3094405586be6d755be562dbe497f Mon Sep 17 00:00:00 2001 From: praschke Date: Mon, 16 Oct 2023 23:27:14 +0100 Subject: docs: typeof this shouldn't be used as a block helper, the result may be non-portable --- docs/templates.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/docs/templates.md b/docs/templates.md index b99702b3..f5eeb95e 100644 --- a/docs/templates.md +++ b/docs/templates.md @@ -543,7 +543,7 @@ Returns the type of a value.
    Syntax: - {{#typeof value}}{{/typeof}}
    + {{typeof value}}
    {{#typeof}}value{{/typeof}}
    * _`value`_
    @@ -553,8 +553,8 @@ Returns the type of a value. Example: ```handlebars - {{#typeof "よみちゃん"}}{{/typeof}} - {{#typeof 1}}{{/typeof}} + {{typeof "よみちゃん"}} + {{typeof 1}} {{#typeof}}よみちゃん{{/typeof}} ``` -- cgit v1.2.3 From 5dc0deb51239b2ed0ab04f3e232e3ceb6e93ea03 Mon Sep 17 00:00:00 2001 From: praschke Date: Mon, 16 Oct 2023 23:29:17 +0100 Subject: docs: join and concat --- docs/templates.md | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/docs/templates.md b/docs/templates.md index f5eeb95e..3ae8c58e 100644 --- a/docs/templates.md +++ b/docs/templates.md @@ -574,7 +574,7 @@ Joins the arguments to a single string with a separator, flattening any argument
    Syntax: - {{#join separator value1 value2 valueN...}}{{/join}}
    + {{join separator value1 value2 valueN...}}
    * _`separator`_
    The separator string to use between values. @@ -585,8 +585,8 @@ Joins the arguments to a single string with a separator, flattening any argument Example: ```handlebars - {{#set "index" 32}}{{/set~}} - {{~#join "_" "yomichan" (get "index") "value"}}{{/join}} + {{set "index" 32~}} + {{~join "_" "yomichan" (get "index") "value"}} ``` Output: @@ -603,7 +603,7 @@ Joins the arguments to a single string, without flattening arguments that are ar
    Syntax: - {{#concat value1 value1 valueN...}}{{/concat}}
    + {{concat value1 value1 valueN...}}
    * _`valueN`_
    A value to join into the resulting string @@ -612,8 +612,8 @@ Joins the arguments to a single string, without flattening arguments that are ar Example: ```handlebars - {{#set "index" 32}}{{/set~}} - {{~#concat "yomichan_" (get "index") "_value"}}{{/concat}} + {{set "index" 32~}} + {{~concat "yomichan_" (get "index") "_value"}} ``` Output: -- cgit v1.2.3 From f6ffe2ffd7d610310521c79cdf9e4e776aa96de1 Mon Sep 17 00:00:00 2001 From: praschke Date: Mon, 16 Oct 2023 23:39:46 +0100 Subject: docs: pitchCategories --- docs/templates.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/templates.md b/docs/templates.md index 3ae8c58e..94d4cc93 100644 --- a/docs/templates.md +++ b/docs/templates.md @@ -630,7 +630,7 @@ Returns an array representing the different pitch categories for a specific term
    Syntax: - {{#pitchCategories @root}}{{/pitchCategories}}
    + {{pitchCategories @root}}
    * _`@root`_
    The argument passed should always be the root data object. -- cgit v1.2.3 From 18757dc0a0b8b2491864112fe07f8aed0aa74df0 Mon Sep 17 00:00:00 2001 From: praschke Date: Mon, 16 Oct 2023 23:47:47 +0100 Subject: docs: hiragana and katakana --- docs/templates.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/docs/templates.md b/docs/templates.md index 94d4cc93..dcdf9d1b 100644 --- a/docs/templates.md +++ b/docs/templates.md @@ -786,7 +786,7 @@ Converts katakana text to hiragana.
    Syntax: - {{#hiragana value [keepProlongedSoundMarks=true|false]}}{{/hiragana}}
    + {{hiragana value [keepProlongedSoundMarks=true|false]}}
    {{#hiragana [keepProlongedSoundMarks=true|false]}}value{{/hiragana}}
    * _`value`_
    @@ -799,7 +799,7 @@ Converts katakana text to hiragana. Example: ```handlebars - {{#hiragana "よみちゃん ヨミちゃん ヨミチャン"}}{{/hiragana}} + {{hiragana "よみちゃん ヨミちゃん ヨミチャン"}} {{#hiragana}}よみちゃん ヨミちゃん ヨミチャン{{/hiragana}} {{#hiragana}}ローマ字{{/hiragana}} {{#hiragana keepProlongedSoundMarks=true}}ローマ字{{/hiragana}} @@ -822,7 +822,7 @@ Converts hiragana text to katakana.
    Syntax: - {{#katakana text}}{{/katakana}}
    + {{katakana text}}
    {{#katakana}}text{{/katakana}}
    * _`text`_
    @@ -832,7 +832,7 @@ Converts hiragana text to katakana. Example: ```handlebars - {{#katakana "よみちゃん ヨミちゃん ヨミチャン"}}{{/katakana}} + {{katakana "よみちゃん ヨミちゃん ヨミチャン"}} {{#katakana}}よみちゃん ヨミちゃん ヨミチャン{{/katakana}} ``` -- cgit v1.2.3 From 3b886960050e9c41071e032b0cf92d0d5ab547f5 Mon Sep 17 00:00:00 2001 From: praschke Date: Sun, 22 Oct 2023 14:33:33 +0100 Subject: catch a few more cases in the template patch --- .../anki-field-templates-upgrade-v21.handlebars | 98 ++++++++++++---------- 1 file changed, 54 insertions(+), 44 deletions(-) diff --git a/ext/data/templates/anki-field-templates-upgrade-v21.handlebars b/ext/data/templates/anki-field-templates-upgrade-v21.handlebars index 4d88b812..33c4dc6c 100644 --- a/ext/data/templates/anki-field-templates-upgrade-v21.handlebars +++ b/ext/data/templates/anki-field-templates-upgrade-v21.handlebars @@ -1,85 +1,91 @@ {{<<<<<<<}} -{{~#set "any" false}}{{/set~}} +{{#formatGlossary ../dictionary}}{{{.}}}{{/formatGlossary}} {{=======}} -{{~set "any" false~}} +{{formatGlossary ../dictionary .}} {{>>>>>>>}} {{<<<<<<<}} -{{~#set "any" true}}{{/set~}} +{{~#furigana}}{{{.}}}{{/furigana~}} {{=======}} -{{~set "any" true~}} +{{~furigana .~}} {{>>>>>>>}} {{<<<<<<<}} -{{#each glossary}}{{#formatGlossary ../dictionary}}{{{.}}}{{/formatGlossary}}{{/each}} +{{#furigana}}{{{definition}}}{{/furigana}} {{=======}} -{{#each glossary}}{{formatGlossary ../dictionary .}}{{/each}} +{{furigana definition}} {{>>>>>>>}} {{<<<<<<<}} -{{#each glossary}}{{#formatGlossary ../dictionary}}{{{.}}}{{/formatGlossary}}{{#unless @last}} | {{/unless}}{{/each}} +{{~#furigana expression reading~}}{{~/furigana~}} {{=======}} -{{#each glossary}}{{formatGlossary ../dictionary .}}{{#unless @last}} | {{/unless}}{{/each}} +{{~furigana expression reading~}} {{>>>>>>>}} {{<<<<<<<}} -
      {{#each glossary}}
    • {{#formatGlossary ../dictionary}}{{{.}}}{{/formatGlossary}}
    • {{/each}}
    +{{~#furigana expression reading}}{{/furigana~}} {{=======}} -
      {{#each glossary}}
    • {{formatGlossary ../dictionary .}}
    • {{/each}}
    +{{~furigana expression reading~}} {{>>>>>>>}} {{<<<<<<<}} -{{~#set "previousDictionary" dictionary~}}{{~/set~}} +{{~#furiganaPlain}}{{{.}}}{{/furiganaPlain~}} {{=======}} -{{~set "previousDictionary" dictionary~}} +{{~furiganaPlain .~}} {{>>>>>>>}} {{<<<<<<<}} -[sound:{{#getMedia "audio"}}{{/getMedia}}] +{{#furiganaPlain}}{{{definition}}}{{/furiganaPlain}} {{=======}} -[sound:{{getMedia "audio"}}] +{{furiganaPlain definition}} {{>>>>>>>}} {{<<<<<<<}} -{{~#furigana}}{{{.}}}{{/furigana~}} +{{~#furiganaPlain expression reading~}}{{~/furiganaPlain~}} {{=======}} -{{~furigana .~}} +{{~furiganaPlain expression reading~}} {{>>>>>>>}} {{<<<<<<<}} -{{#furigana}}{{{definition}}}{{/furigana}} +{{~#furiganaPlain expression reading}}{{/furiganaPlain~}} {{=======}} -{{furigana definition}} +{{~furiganaPlain expression reading~}} {{>>>>>>>}} {{<<<<<<<}} -{{~#furiganaPlain}}{{{.}}}{{/furiganaPlain~}} +{{#getMedia "audio"}}{{/getMedia}} {{=======}} -{{~furiganaPlain .~}} +{{getMedia "audio"}} {{>>>>>>>}} {{<<<<<<<}} -{{#furiganaPlain}}{{{definition}}}{{/furiganaPlain}} +{{#getMedia "screenshot"}}{{/getMedia}} {{=======}} -{{furiganaPlain definition}} +{{getMedia "screenshot"}} {{>>>>>>>}} {{<<<<<<<}} - +{{#getMedia "clipboardImage"}}{{/getMedia}} {{=======}} - +{{getMedia "clipboardImage"}} {{>>>>>>>}} {{<<<<<<<}} - +{{#getMedia "clipboardText"}}{{/getMedia}} {{=======}} - +{{getMedia "clipboardText"}} {{>>>>>>>}} {{<<<<<<<}} -{{~#if (hasMedia "clipboardText")}}{{#getMedia "clipboardText"}}{{/getMedia}}{{/if~}} +{{#getMedia "selectionText"}}{{/getMedia}} {{=======}} -{{~#if (hasMedia "clipboardText")}}{{getMedia "clipboardText"}}{{/if~}} +{{getMedia "selectionText"}} +{{>>>>>>>}} + +{{<<<<<<<}} +{{#getMedia "textFurigana" definition.cloze.sentence escape=false}}{{/getMedia}} +{{=======}} +{{getMedia "textFurigana" definition.cloze.sentence escape=false}} {{>>>>>>>}} {{<<<<<<<}} @@ -89,9 +95,21 @@ {{>>>>>>>}} {{<<<<<<<}} -{{~#furigana expression reading~}}{{~/furigana~}} +{{~#set "any" false}}{{/set~}} {{=======}} -{{~furigana expression reading~}} +{{~set "any" false~}} +{{>>>>>>>}} + +{{<<<<<<<}} +{{~#set "any" true}}{{/set~}} +{{=======}} +{{~set "any" true~}} +{{>>>>>>>}} + +{{<<<<<<<}} +{{~#set "previousDictionary" dictionary~}}{{~/set~}} +{{=======}} +{{~set "previousDictionary" dictionary~}} {{>>>>>>>}} {{<<<<<<<}} @@ -107,9 +125,9 @@ {{>>>>>>>}} {{<<<<<<<}} -{{~#get "separator"}}{{/get~}}{{{.}}} +{{~#get "separator"}}{{/get~}} {{=======}} -{{~get "separator"~}}{{{.}}} +{{~get "separator"~}} {{>>>>>>>}} {{<<<<<<<}} @@ -131,21 +149,13 @@ {{>>>>>>>}} {{<<<<<<<}} - {{~#set (concat "used_" .) true~}}{{~/set~}} - {{~#set "first" false~}}{{~/set~}} +{{~#set "first" false~}}{{~/set~}} {{=======}} - {{~set (concat "used_" .) true~}} - {{~set "first" false~}} +{{~set "first" false~}} {{>>>>>>>}} {{<<<<<<<}} -{{~#if (hasMedia "selectionText")}}{{#getMedia "selectionText"}}{{/getMedia}}{{/if~}} +{{~#set (concat "used_" .) true~}}{{~/set~}} {{=======}} -{{~#if (hasMedia "selectionText")}}{{getMedia "selectionText"}}{{/if~}} -{{>>>>>>>}} - -{{<<<<<<<}} -{{#getMedia "textFurigana" definition.cloze.sentence escape=false}}{{/getMedia}} -{{=======}} -{{getMedia "textFurigana" definition.cloze.sentence escape=false}} +{{~set (concat "used_" .) true~}} {{>>>>>>>}} -- cgit v1.2.3 From f88bded2f05b440a8aa7beb980d8c5d76b150011 Mon Sep 17 00:00:00 2001 From: praschke Date: Sun, 22 Oct 2023 15:21:38 +0100 Subject: docs: note changes to custom templates in the readme --- README.md | 23 ++++++++++++++++++++++- docs/templates.md | 12 ++++++------ 2 files changed, 28 insertions(+), 7 deletions(-) diff --git a/README.md b/README.md index 0da2c617..2c838645 100644 --- a/README.md +++ b/README.md @@ -74,6 +74,8 @@ updates automatically. ## Migrating from Yomichan +### Exporting Data + If you are an existing user of Yomichan, you can export your dictionary collection and settings such that they can be imported into Yomitan to reflect your setup exactly as it was. You can export your settings from Yomichan's Settings page. Go to the `Backup` section and click on `Export Settings`. @@ -81,7 +83,26 @@ You can export your settings from Yomichan's Settings page. Go to the `Backup` s Yomichan doesn't have first-class support to export the dictionary collection. Please follow the instructions provided in the following link to export your data: https://github.com/themoeway/yomichan-data-exporter#steps-to-export-the-data -You can them import the exported files into Yomitan from the `Backup` section of the `Settings` page. Please see [the section on importing dictionaries](#importing-dictionaries) further below for more explicit steps. +You can then import the exported files into Yomitan from the `Backup` section of the `Settings` page. Please see [the section on importing dictionaries](#importing-dictionaries) further below for more explicit steps. + +### Custom Templates + +If you do not use custom templates for Anki note creation, this section can be skipped. + +Due to security concerns, an alternate implementation of Handlebars is being used which behaves slightly differently. +This revealed a bug in four of Yomitan's template helpers, which have now been fixed in the default templates. If your +custom templates use the following helpers, please ensure their use matches the corrected forms. + +Helper | Example | Corrected +-------|---------|---------- +`formatGlossary` | `{{#formatGlossary ../dictionary}}{{{.}}}{{/formatGlossary}}` | `{{formatGlossary ../dictionary .}}` +`furigana` | `{{#furigana}}{{{definition}}}{{/furigana}}` | `{{furigana definition}}` +`furiganaPlain` | `{{~#furiganaPlain}}{{{.}}}{{/furiganaPlain~}}` | `{{~furiganaPlain .~}}` +`dumpObject` | `{{#dumpObject}}{{{.}}}{{/dumpObject}}` | `{{dumpObject .}}` + +Authors of custom templates may be interested to know that other helpers previously used and documented in the block +form (e.g. `{{#set "key" "value"}}{{/set}}`), while not broken by this change, may also be replaced with the less verbose +form (e.g. `{{set "key" "value"}}`). The default templates and helper documentation have been changed to reflect this. ## Dictionaries diff --git a/docs/templates.md b/docs/templates.md index dcdf9d1b..030ca3d2 100644 --- a/docs/templates.md +++ b/docs/templates.md @@ -235,9 +235,9 @@ Creates a set of all unique tags for the definition and returns a text represent
    -### `eachUpTo` +### `#eachUpTo` -Similar to the built-in `each` function, but iterates up to a maximum count. +Similar to the built-in `#each` function, but iterates up to a maximum count. If the iterable is falsy or empty, the `else` condition will be used.
    @@ -314,7 +314,7 @@ If an unknown operator is specified, the `undefined` value is returned.
    Syntax: - {{#op operator operand1 [operand2] [operand3]}}{{/op}} + {{op operator operand1 [operand2] [operand3]}} * _`operator`_
    One of the unary, binary, or ternary operators. @@ -329,7 +329,7 @@ If an unknown operator is specified, the `undefined` value is returned. Example: ```handlebars - {{#if (op "===" value1 value2)}}Values are equal{{/op~}}
    + {{#if (op "===" value1 value2)}}Values are equal{{/if~}}
    {{~#op "-" value1}}{{/op~}}
    {{~op "?:" value1 "a" "b"}} ``` @@ -399,7 +399,7 @@ Assigns a value to the custom state stack.
    -### `scope` +### `#scope` Pushes a new variable scope to the custom state stack. Variable assignments are applied to the most recent scope, @@ -538,7 +538,7 @@ Returns an array of the mora for a kana string. ### `typeof` -Returns the type of a value. +Returns the type of a value. Use of `#typeof` in the block form may be nonportable.
    Syntax: -- cgit v1.2.3 From 757707539690b6aec45e9de8cd37fdfc907d8843 Mon Sep 17 00:00:00 2001 From: praschke Date: Sun, 22 Oct 2023 17:23:04 +0100 Subject: warn about custom templates in the welcome page --- ext/css/settings.css | 7 +++++++ ext/js/background/backend.js | 20 ++++++-------------- ext/js/data/options-util.js | 27 +++++++++++++++++++++++++++ ext/js/pages/welcome-main.js | 7 +++++++ ext/welcome.html | 27 ++++++++++++++++++++++----- 5 files changed, 69 insertions(+), 19 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/js/background/backend.js b/ext/js/background/backend.js index 565f4abf..755010a3 100644 --- a/ext/js/background/backend.js +++ b/ext/js/background/backend.js @@ -2099,20 +2099,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 7b050416..1f2ffb05 100644 --- a/ext/js/data/options-util.js +++ b/ext/js/data/options-util.js @@ -1001,6 +1001,33 @@ class OptionsUtil { 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/welcome.html b/ext/welcome.html index 14e98367..56167866 100644 --- a/ext/welcome.html +++ b/ext/welcome.html @@ -25,6 +25,19 @@

    Welcome to Yomitan!

    + +
    +
    +
    +

    + There are custom Anki templates in your settings. Note that some syntax has changed from previous versions of Yomitan. + Please ensure that your custom templates are using the updated syntax. +

    +
    +
    +
    + +

    Here are some basics to get started

    @@ -49,10 +62,9 @@
    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 Yomitan homepage, - allowing you to choose the dictionaries most relevant for you. + Several downloadable dictionaries can be found on the Yomitan homepage. Dictionaries can be configured using the button below, - or later from the the Settings page. + or later from the Settings page.
    @@ -67,12 +79,17 @@
    - You can also import an exported collection of dictionaries to migrate from a different device or browser from the Backup section of the Settings page. + You can also import an exported collection of dictionaries from the Backup section of the Settings page.

    - 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 Yomitan's README for that. + +

    + + If you are using or planning to use custom templates for Anki note creation, note that some syntax has changed from Yomichan and Yomibaba. + Please ensure that your custom templates are using the updated syntax.
    -- cgit v1.2.3