Frequencies marker (#1074)
* Update japanese.js tests * Simplify fallback/early exit * Add overloads to furigana and furiganaPlain handlebars helper functions * Expose unique expression/reading arrays (and subsequently counts) * Add {frequencies} marker
This commit is contained in:
parent
94d63f4f87
commit
008ffdb6bf
@ -163,6 +163,7 @@ Flashcard fields can be configured with the following steps:
|
||||
`{dictionary}` | Name of the dictionary from which the card is being created (unavailable in *grouped* mode).
|
||||
`{document-title}` | Title of the web page that the term appeared in.
|
||||
`{expression}` | Term expressed as kanji (will be displayed in kana if kanji is not available).
|
||||
`{frequencies}` | Frequency information for the term.
|
||||
`{furigana}` | Term expressed as kanji with furigana displayed above it (e.g. <ruby>日本語<rt>にほんご</rt></ruby>).
|
||||
`{furigana-plain}` | Term expressed as kanji with furigana displayed next to it in brackets (e.g. 日本語[にほんご]).
|
||||
`{glossary}` | List of definitions for the term (output format depends on whether running in *grouped* mode).
|
||||
@ -188,6 +189,7 @@ Flashcard fields can be configured with the following steps:
|
||||
`{cloze-suffix}` | Fragment of the containing `{sentence}` starting at the end of `{cloze-body}` until the end of `{sentence}`.
|
||||
`{dictionary}` | Name of the dictionary from which the card is being created.
|
||||
`{document-title}` | Title of the web page that the kanji appeared in.
|
||||
`{frequencies}` | Frequency information for the kanji.
|
||||
`{glossary}` | List of definitions for the kanji.
|
||||
`{kunyomi}` | Kunyomi (Japanese reading) for the kanji expressed as katakana.
|
||||
`{onyomi}` | Onyomi (Chinese reading) for the kanji expressed as hiragana.
|
||||
|
@ -44,21 +44,27 @@ This function can be helpful for debugging values when creating templates.
|
||||
|
||||
### `furigana`
|
||||
|
||||
Converts a definition to its furigana representation.
|
||||
Converts a definition or expression/reading pair to its furigana representation.
|
||||
|
||||
<details>
|
||||
<summary>Syntax:</summary>
|
||||
|
||||
<code>{{#furigana}}<i><definition></i>{{/furigana}}</code>
|
||||
<code>{{#furigana}}<i><definition></i>{{/furigana}}</code><br>
|
||||
<code>{{#furigana <i>expression</i> <i>reading</i>}}{{/furigana}}</code><br>
|
||||
|
||||
* _`definition`_ <br>
|
||||
The definition to convert.
|
||||
* _`expression`_ <br>
|
||||
The expression to convert.
|
||||
* _`reading`_ <br>
|
||||
The reading to convert.
|
||||
</details>
|
||||
<details>
|
||||
<summary>Example:</summary>
|
||||
|
||||
```handlebars
|
||||
{{#furigana}}{{.}}{{/furigana}}
|
||||
{{#furigana "読む" "よむ"}}{{/furigana}}
|
||||
```
|
||||
|
||||
Output:
|
||||
@ -73,21 +79,27 @@ Converts a definition to its furigana representation.
|
||||
|
||||
### `furiganaPlain`
|
||||
|
||||
Converts a definition to its simplified furigana representation.
|
||||
Converts a definition or expression/reading pair to its simplified furigana representation.
|
||||
|
||||
<details>
|
||||
<summary>Syntax:</summary>
|
||||
|
||||
<code>{{#furiganaPlain}}<i><definition></i>{{/furigana}}</code>
|
||||
<code>{{#furiganaPlain <i>expression</i> <i>reading</i>}}{{/furiganaPlain}}</code><br>
|
||||
|
||||
* _`definition`_ <br>
|
||||
The definition to convert.
|
||||
* _`expression`_ <br>
|
||||
The expression to convert.
|
||||
* _`reading`_ <br>
|
||||
The reading to convert.
|
||||
</details>
|
||||
<details>
|
||||
<summary>Example:</summary>
|
||||
|
||||
```handlebars
|
||||
{{~#furiganaPlain~}}{{.}}{{~/furiganaPlain~}}
|
||||
{{#furiganaPlain "読む" "よむ"}}{{/furiganaPlain}}
|
||||
```
|
||||
|
||||
Output:
|
||||
|
@ -6,3 +6,20 @@
|
||||
{{~/each~}}
|
||||
{{~/if~}}
|
||||
{{/inline}}
|
||||
|
||||
{{#*inline "frequencies"}}
|
||||
{{~#if (op ">" definition.frequencies.length 0)~}}
|
||||
<ul style="text-align: left;">
|
||||
{{~#each definition.frequencies~}}
|
||||
<li>
|
||||
{{~#if (op "!==" ../definition.type "kanji")~}}
|
||||
{{~#if (op "||" (op ">" ../uniqueExpressions.length 1) (op ">" ../uniqueReadings.length 1))~}}(
|
||||
{{~#furigana expression reading~}}{{~/furigana~}}
|
||||
) {{/if~}}
|
||||
{{~/if~}}
|
||||
{{~dictionary}}: {{frequency~}}
|
||||
</li>
|
||||
{{~/each~}}
|
||||
</ul>
|
||||
{{~/if~}}
|
||||
{{/inline}}
|
||||
|
@ -306,4 +306,21 @@
|
||||
{{~/if~}}
|
||||
{{/inline}}
|
||||
|
||||
{{#*inline "frequencies"}}
|
||||
{{~#if (op ">" definition.frequencies.length 0)~}}
|
||||
<ul style="text-align: left;">
|
||||
{{~#each definition.frequencies~}}
|
||||
<li>
|
||||
{{~#if (op "!==" ../definition.type "kanji")~}}
|
||||
{{~#if (op "||" (op ">" ../uniqueExpressions.length 1) (op ">" ../uniqueReadings.length 1))~}}(
|
||||
{{~#furigana expression reading~}}{{~/furigana~}}
|
||||
) {{/if~}}
|
||||
{{~/if~}}
|
||||
{{~dictionary}}: {{frequency~}}
|
||||
</li>
|
||||
{{~/each~}}
|
||||
</ul>
|
||||
{{~/if~}}
|
||||
{{/inline}}
|
||||
|
||||
{{~> (lookup . "marker") ~}}
|
||||
|
@ -108,9 +108,19 @@ class AnkiNoteBuilder {
|
||||
_createNoteData(definition, mode, context, resultOutputMode, glossaryLayoutMode, compactTags) {
|
||||
const pitches = DictionaryDataUtil.getPitchAccentInfos(definition);
|
||||
const pitchCount = pitches.reduce((i, v) => i + v.pitches.length, 0);
|
||||
const uniqueExpressions = new Set();
|
||||
const uniqueReadings = new Set();
|
||||
if (definition.type !== 'kanji') {
|
||||
for (const {expression, reading} of definition.expressions) {
|
||||
uniqueExpressions.add(expression);
|
||||
uniqueReadings.add(reading);
|
||||
}
|
||||
}
|
||||
return {
|
||||
marker: null,
|
||||
definition,
|
||||
uniqueExpressions: [...uniqueExpressions],
|
||||
uniqueReadings: [...uniqueReadings],
|
||||
pitches,
|
||||
pitchCount,
|
||||
group: resultOutputMode === 'group',
|
||||
|
@ -83,6 +83,7 @@ class AnkiController {
|
||||
'dictionary',
|
||||
'document-title',
|
||||
'expression',
|
||||
'frequencies',
|
||||
'furigana',
|
||||
'furigana-plain',
|
||||
'glossary',
|
||||
|
@ -117,13 +117,13 @@ class TemplateRenderer {
|
||||
return this._escape(dump);
|
||||
}
|
||||
|
||||
_furigana(context, options) {
|
||||
const definition = options.fn(context);
|
||||
const segs = jp.distributeFurigana(definition.expression, definition.reading);
|
||||
_furigana(context, ...args) {
|
||||
const {expression, reading} = this._getFuriganaExpressionAndReading(context, ...args);
|
||||
const segs = jp.distributeFurigana(expression, reading);
|
||||
|
||||
let result = '';
|
||||
for (const seg of segs) {
|
||||
if (seg.furigana) {
|
||||
if (seg.furigana.length > 0) {
|
||||
result += `<ruby>${seg.text}<rt>${seg.furigana}</rt></ruby>`;
|
||||
} else {
|
||||
result += seg.text;
|
||||
@ -133,20 +133,31 @@ class TemplateRenderer {
|
||||
return result;
|
||||
}
|
||||
|
||||
_furiganaPlain(context, options) {
|
||||
const definition = options.fn(context);
|
||||
const segs = jp.distributeFurigana(definition.expression, definition.reading);
|
||||
_furiganaPlain(context, ...args) {
|
||||
const {expression, reading} = this._getFuriganaExpressionAndReading(context, ...args);
|
||||
const segs = jp.distributeFurigana(expression, reading);
|
||||
|
||||
let result = '';
|
||||
for (const seg of segs) {
|
||||
if (seg.furigana) {
|
||||
result += ` ${seg.text}[${seg.furigana}]`;
|
||||
if (seg.furigana.length > 0) {
|
||||
if (result.length > 0) { result += ' '; }
|
||||
result += `${seg.text}[${seg.furigana}]`;
|
||||
} else {
|
||||
result += seg.text;
|
||||
}
|
||||
}
|
||||
|
||||
return result.trimLeft();
|
||||
return result;
|
||||
}
|
||||
|
||||
_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);
|
||||
return {expression, reading};
|
||||
}
|
||||
}
|
||||
|
||||
_kanjiLinks(context, options) {
|
||||
|
@ -411,9 +411,9 @@ const jp = (() => {
|
||||
// Furigana distribution
|
||||
|
||||
distributeFurigana(expression, reading) {
|
||||
const fallback = [{furigana: reading, text: expression}];
|
||||
if (!reading) {
|
||||
return fallback;
|
||||
if (!reading || reading === expression) {
|
||||
// Same
|
||||
return [{furigana: '', text: expression}];
|
||||
}
|
||||
|
||||
let isAmbiguous = false;
|
||||
@ -471,7 +471,9 @@ const jp = (() => {
|
||||
if (segments && !isAmbiguous) {
|
||||
return segments;
|
||||
}
|
||||
return fallback;
|
||||
|
||||
// Fallback
|
||||
return [{furigana: reading, text: expression}];
|
||||
}
|
||||
|
||||
distributeFuriganaInflected(expression, reading, source) {
|
||||
|
@ -334,6 +334,25 @@ function testDistributeFurigana() {
|
||||
[
|
||||
{text: '長い間', furigana: 'ながいあいだ'}
|
||||
]
|
||||
],
|
||||
// Same/empty reading
|
||||
[
|
||||
['飼い犬', ''],
|
||||
[
|
||||
{text: '飼い犬', furigana: ''}
|
||||
]
|
||||
],
|
||||
[
|
||||
['かいいぬ', 'かいいぬ'],
|
||||
[
|
||||
{text: 'かいいぬ', furigana: ''}
|
||||
]
|
||||
],
|
||||
[
|
||||
['かいぬ', 'かいぬ'],
|
||||
[
|
||||
{text: 'かいぬ', furigana: ''}
|
||||
]
|
||||
]
|
||||
];
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user