summaryrefslogtreecommitdiff
path: root/ext/js/templates/sandbox/anki-template-renderer.js
diff options
context:
space:
mode:
Diffstat (limited to 'ext/js/templates/sandbox/anki-template-renderer.js')
-rw-r--r--ext/js/templates/sandbox/anki-template-renderer.js54
1 files changed, 20 insertions, 34 deletions
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) {