aboutsummaryrefslogtreecommitdiff
path: root/docs
diff options
context:
space:
mode:
Diffstat (limited to 'docs')
-rw-r--r--docs/templates.md577
1 files changed, 577 insertions, 0 deletions
diff --git a/docs/templates.md b/docs/templates.md
new file mode 100644
index 00000000..1c9081d2
--- /dev/null
+++ b/docs/templates.md
@@ -0,0 +1,577 @@
+# Templates
+
+## Helpers
+
+Yomichan supports several custom Handlebars helpers for rendering templates.
+The source code for these templates can be found [here](../ext/bg/js/template-renderer.js).
+
+
+### `dumpObject`
+
+Converts an object to a pretty-printed JSON string.
+This function can be helpful for debugging values when creating templates.
+
+<details>
+ <summary>Syntax:</summary>
+
+ <code>{{#dumpObject}}<i>&lt;object&gt;</i>{{/dumpObject}}</code>
+
+ * _`object`_ <br>
+ The object to convert.
+</details>
+<details>
+ <summary>Example:</summary>
+
+ ```handlebars
+ <pre>{{#dumpObject}}{{.}}{{/dumpObject}}</pre>
+ ```
+
+ Output:
+ ```html
+ <pre>{
+ "key": "value"
+ }</pre>
+ ```
+
+ Preview:
+ ```html
+ {
+ "key": "value"
+ }
+ ```
+</details>
+
+
+### `furigana`
+
+Converts a definition to its furigana representation.
+
+<details>
+ <summary>Syntax:</summary>
+
+ <code>{{#furigana}}<i>&lt;definition&gt;</i>{{/furigana}}</code>
+
+ * _`definition`_ <br>
+ The definition to convert.
+</details>
+<details>
+ <summary>Example:</summary>
+
+ ```handlebars
+ {{#furigana}}{{.}}{{/furigana}}
+ ```
+
+ Output:
+ ```html
+ <ruby>読<rt>よ</rt></ruby>む
+ ```
+
+ Preview
+ <pre><ruby>読<rt>よ</rt></ruby>む</pre>
+</details>
+
+
+### `furiganaPlain`
+
+Converts a definition to its simplified furigana representation.
+
+<details>
+ <summary>Syntax:</summary>
+
+ <code>{{#furiganaPlain}}<i>&lt;definition&gt;</i>{{/furigana}}</code>
+
+ * _`definition`_ <br>
+ The definition to convert.
+</details>
+<details>
+ <summary>Example:</summary>
+
+ ```handlebars
+ {{~#furiganaPlain~}}{{.}}{{~/furiganaPlain~}}
+ ```
+
+ Output:
+ ```html
+ 読[よ]む
+ ```
+</details>
+
+
+### `multiLine`
+
+Replaces newline characters with a forced HTML line break `<br>`.
+
+<details>
+ <summary>Syntax:</summary>
+
+ <code>{{#multiLine}}<i>text with multiple lines</i>{{/multiLine}}</code>
+</details>
+<details>
+ <summary>Example:</summary>
+
+ ```handlebars
+ {{#kanjiLinks~}}
+ some
+ multiline
+ text
+ {{~/kanjiLinks}}
+ ```
+
+ Output:
+ ```html
+ some<br>multiline<br>text
+ ```
+
+ Preview:
+ <pre>some<br>multiline<br>text</pre>
+</details>
+
+
+### `regexReplace`
+
+Uses a [regular expression](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Regular_Expressions) to replace a pattern with the specified text.
+
+<details>
+ <summary>Syntax:</summary>
+
+ <code>{{#regexReplace <i>regex</i> <i>replacement</i> <i>[flags]</i>}}<i>text-to-modify</i>{{/regexReplace}}</code>
+
+ * _`regex`_ <br>
+ 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.
+ * _`replacement`_ <br>
+ The text used to replace pattern matches. This supports the standard [special capture group replacements](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/replace#Specifying_a_string_as_a_parameter) as supported by the web browser.
+ * _`flags`_ _(optional)_ <br>
+ Optional flags to pass to the [`RegExp`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/RegExp/RegExp) constructor.
+ * _`text-to-modify`_ <br>
+ The text that the regular expression is applied to.
+</details>
+<details>
+ <summary>Example:</summary>
+
+ ```handlebars
+ {{#regexReplace "\(([^)]*)\)" "$1" "g"~}}Here is (some) (text) (in) (parentheses){{~/regexReplace}}
+ ```
+
+ Output:
+ ```html
+ Here is some text in parentheses
+ ```
+</details>
+
+
+### `regexMatch`
+
+Uses a [regular expression](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Regular_Expressions) to return only the content that matches the pattern.
+
+<details>
+ <summary>Syntax:</summary>
+
+ <code>{{#regexMatch <i>regex</i> <i>[flags]</i>}}<i>text-to-modify</i>{{/regexMatch}}</code>
+
+ * _`regex`_ <br>
+ 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.
+ * _`flags`_ _(optional)_ <br>
+ Optional flags to pass to the [`RegExp`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/RegExp/RegExp) constructor.
+ * _`text-to-modify`_ <br>
+ The text that the regular expression is applied to.
+</details>
+<details>
+ <summary>Example:</summary>
+
+ ```handlebars
+ {{#regexMatch "\(([^)]*)\)" "g"~}}Here is (some) (text) (in) (parentheses){{~/regexMatch}}
+ ```
+
+ Output:
+ ```html
+ (some)(text)(in)(parentheses)
+ ```
+</details>
+
+
+### `mergeTags`
+
+Creates a set of all unique tags for the definition and returns a text representation of the tags separated by commas.
+
+<details>
+ <summary>Syntax:</summary>
+
+ <code>{{#mergeTags <i>definition</i> <i>isGroupMode</i> <i>isMergeMode</i>}}{{/mergeTags}}</code>
+
+ * _`definition`_ <br>
+ The root definition object.
+ * _`isGroupMode`_ _(optional)_ <br>
+ Whether or not the display mode is the 'group' mode.
+ * _`isMergeMode`_ <br>
+ Whether or not the display mode is the 'merge' mode.
+</details>
+<details>
+ <summary>Example:</summary>
+
+ ```handlebars
+ {{~#mergeTags definition group merge}}{{/mergeTags~}}
+ ```
+
+ Output:
+ ```html
+ v5m, vt, JMdict (English)
+ ```
+</details>
+
+
+### `eachUpTo`
+
+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.
+
+<details>
+ <summary>Syntax:</summary>
+
+ <code>{{#eachUpTo <i>iterable</i> <i>maxCount</i>}}<i>(modification)</i>{{else}}<i>(else-modification)</i>{{/eachUpTo}}</code>
+
+ * _`iterable`_ <br>
+ The object that should be looped over. A JavaScript [`for...of`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/for...of) loop is used, so the object only needs to be iterable.
+ * _`maxCount`_ _(optional)_ <br>
+ The maximum number of entries to loop over.
+ * _`modification`_ <br>
+ The template used to modify the value. The context is changed to the current item of iteration.
+ * _`else-modification`_ <br>
+ The template used in case the iterable is falsy or empty. The context is unchanged.
+</details>
+<details>
+ <summary>Example:</summary>
+
+ ```handlebars
+ {{~#eachUpTo someArray 5}}{{{.}}}<br>{{else}}Empty{{/mergeTags~}}
+ ```
+
+ Output:
+ ```html
+ someArray[0]<br>someArray[1]<br>someArray[2]<br>someArray[3]<br>someArray[4]<br>
+ ```
+
+ Preview:
+ <pre>someArray[0]<br>someArray[1]<br>someArray[2]<br>someArray[3]<br>someArray[4]<br></pre>
+</details>
+
+
+### `spread`
+
+Uses the JavaScript [spread](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Spread_syntax) operator to convert one or more iterables into a single array.
+This allows it to be used similar to an [`Array.concat`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/concat) operation.
+
+<details>
+ <summary>Syntax:</summary>
+
+ <code>{{#spread <i>iterable1</i> <i>iterable2</i> <i>...</i> <i>iterableN</i>}}{{/spread}}</code>
+
+ * _`iterableN`_ <br>
+ A variable amount of iterable objects to combine into a single array.
+</details>
+<details>
+ <summary>Example:</summary>
+
+ ```handlebars
+ {{#each (spread array1 array2)}}{{{.}}}<br>{{/each}}
+ ```
+
+ Output:
+ ```html
+ array1[0]<br>array1[1]<br>array2[0]<br>array2[1]<br>
+ ```
+
+ Preview:
+ <pre>array1[0]<br>array1[1]<br>array2[0]<br>array2[1]<br></pre>
+</details>
+
+
+### `op`
+
+Performs a simple operation on one, two, or three arguments. The operations available are:
+
+* Unary operators: `+`, `-`, `~`, `!`
+* Binary operators: `+`, `-`, `/`, `*`, `%`, `**`, `==`, `!=`, `===`, `!==`, `<`, `<=`, `>`, `>=`, `<<`, `>>`, `>>>`, `&`, `|`, `^`, `&&`, `||`
+* Ternary operators: `?:`
+
+If an unknown operator is specified, the `undefined` value is returned.
+
+<details>
+ <summary>Syntax:</summary>
+
+ <code>{{#op <i>operator</i> <i>operand1</i> <i>[operand2]</i> <i>[operand3]</i>}}{{/op}}</code>
+
+ * _`operator`_ <br>
+ One of the unary, binary, or ternary operators.
+ * _`operand1`_ <br>
+ The first operand of the operation.
+ * _`operand2`_ _(Optional)_<br>
+ The second operand of the operation.
+ * _`operand3`_ _(Optional)_<br>
+ The third operand of the operation.
+</details>
+<details>
+ <summary>Example:</summary>
+
+ ```handlebars
+ {{#if (op "===" value1 value2)}}Values are equal{{/op~}}<br>
+ {{~#op "-" value1}}{{/op~}}<br>
+ {{~#op "?:" value1 "a" "b"}}{{/op}}
+ ```
+
+ Output:
+ ```html
+ Values are equal<br>-32<br>a
+ ```
+
+ Preview:
+ <pre>Values are equal<br>-32<br>a</pre>
+</details>
+
+
+### `get`
+
+Gets a value from the custom state stack.
+
+<details>
+ <summary>Syntax:</summary>
+
+ <code>{{#get <i>name</i>}}{{/get}}</code>
+
+ * _`name`_ <br>
+ The name of the variable to get.
+</details>
+<details>
+ <summary>Example:</summary>
+
+ ```handlebars
+ {{#get "some-text"}}{{/get}}
+ ```
+
+ Output:
+ ```html
+ This is the value of some-text!
+ ```
+</details>
+
+
+### `set`
+
+Assigns a value to the custom state stack.
+
+<details>
+ <summary>Syntax:</summary>
+
+ <code>{{#set <i>name</i>}}<i>value</i>{{/get}}</code><br>
+ <code>{{#set <i>name</i> <i>value</i>}}{{/get}}</code><br>
+
+ * _`name`_ <br>
+ The name of the variable to assign.
+ * _`value`_ <br>
+ The value of the variable.
+</details>
+<details>
+ <summary>Example:</summary>
+
+ ```handlebars
+ {{#set "some-text"}}This is the value of some-text!{{/set~}}
+ {{~#set "some-number" 32}}{{/set}}
+ ```
+
+ Output:
+ ```html
+ ```
+</details>
+
+
+### `scope`
+
+Pushes a new variable scope to the custom state stack.
+Variable assignments are applied to the most recent scope,
+and variable lookups will start from the most recent scope and work backwards until a value is found.
+
+<details>
+ <summary>Syntax:</summary>
+
+ <code>{{#scope}}<i>content</i>{{/scope}}</code>
+
+ * _`name`_ <br>
+ The name of the variable to assign.
+ * _`value`_ <br>
+ The value of the variable.
+</details>
+<details>
+ <summary>Example:</summary>
+
+ ```handlebars
+ {{~#set "key" 32}}{{/set~}}
+ {{~#get "key"}}{{/get~}},
+ {{~#scope~}}
+ {{~#get "key"}}{{/get~}},
+ {{~#set "key" 64}}{{/set~}}
+ {{~#get "key"}}{{/get~}},
+ {{~/scope~}}
+ {{~#get "key"}}{{/get~}}
+ ```
+
+ Output:
+ ```html
+ 32,32,64,32
+ ```
+</details>
+
+
+### `property`
+
+Repeatedly gets a property of an object.
+
+<details>
+ <summary>Syntax:</summary>
+
+ <code>{{#property <i>object</i> <i>property1</i> <i>property2</i> <i>...</i> <i>propertyN</i>}}{{/property}}</code>
+
+ * _`object`_ <br>
+ The initial object to use.
+ * _`propertyN`_ <br>
+ A chain of property names to get on the object.
+</details>
+<details>
+ <summary>Example:</summary>
+
+ ```handlebars
+ {{property someObject "field" 0 "toString"}}
+ ```
+
+ Output:
+ ```html
+ function toString() { [native code] }
+ ```
+</details>
+
+
+### `noop`
+
+No-op. Returns the inner contents of the template.
+
+<details>
+ <summary>Syntax:</summary>
+
+ <code>{{#noop}}<i>content</i>{{/noop}}</code>
+</details>
+<details>
+ <summary>Example:</summary>
+
+ ```handlebars
+ {{noop}}Unchanged content{{/noop}}
+ ```
+
+ Output:
+ ```html
+ Unchanged content
+ ```
+</details>
+
+
+### `isMoraPitchHigh`
+
+Returns whether or not a mora will have a high pitch, given the index of the mora and the position of the downstep.
+
+<details>
+ <summary>Syntax:</summary>
+
+ <code>{{#isMoraPitchHigh <i>index</i> <i>position</i>}}{{/isMoraPitchHigh}}</code>
+</details>
+<details>
+ <summary>Example:</summary>
+
+ ```handlebars
+ {{#if (isMoraPitchHigh 1 2)}}High pitch{{else}}Low pitch{{/if}}
+ ```
+
+ Output:
+ ```html
+ High pitch
+ ```
+</details>
+
+
+### `getKanaMorae`
+
+Returns an array of the mora for a kana string.
+
+<details>
+ <summary>Syntax:</summary>
+
+ <code>{{#getKanaMorae <i>kana-string</i>}}{{/getKanaMorae}}</code>
+</details>
+<details>
+ <summary>Example:</summary>
+
+ ```handlebars
+ {{#each (getKanaMorae "よみちゃん")}}{{{.}}}<br>{{/each}}
+ ```
+
+ Output:
+ ```html
+ よ<br>み<br>ちゃ<br>ん<br>
+ ```
+
+ Preview:
+ <pre>よ<br>み<br>ちゃ<br>ん<br></pre>
+</details>
+
+
+## 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.
+
+<details>
+ <summary>Syntax:</summary>
+
+ <code>{{#kanjiLinks}}<i>text</i>{{/kanjiLinks}}</code>
+</details>
+<details>
+ <summary>Example:</summary>
+
+ ```handlebars
+ {{#kanjiLinks}}読む{{/kanjiLinks}}
+ ```
+
+ Output:
+ ```html
+ <a href="#" class="kanji-link">読</a>む
+ ```
+
+ Preview:
+ <pre><a href="#" class="kanji-link">読</a>む</pre>
+</details>
+
+
+### `sanitizeCssClass`
+
+Sanitizes text so it can be used as a CSS class name.
+
+<details>
+ <summary>Syntax:</summary>
+
+ <code>{{#sanitizeCssClass}}<i>text</i>{{/sanitizeCssClass}}</code>
+</details>
+<details>
+ <summary>Example:</summary>
+
+ ```handlebars
+ {{#sanitizeCssClass}}some text with many types of characters !@#$%^ 読む{{/sanitizeCssClass}}
+ ```
+
+ Output:
+ ```html
+ some_text_with_many_types_of_characters________読む
+ ```
+</details>