Refactor furigana segment data (#1502)
* Remove redundant language assignment * Segment furigana from DisplayGenerator * Remove furiganaSegments from translator data * Add backwards compatibility for furiganaSegments * Update tests
This commit is contained in:
parent
7793e14e57
commit
19f6bf5a3a
@ -31,7 +31,7 @@
|
|||||||
<div class="debug-info"><a class="debug-log-link">Log debug info to console</a></div>
|
<div class="debug-info"><a class="debug-log-link">Log debug info to console</a></div>
|
||||||
</div></template>
|
</div></template>
|
||||||
<template id="expression-template" data-remove-whitespace-text="true"><div class="expression">
|
<template id="expression-template" data-remove-whitespace-text="true"><div class="expression">
|
||||||
<div class="expression-text-container" lang="ja">
|
<div class="expression-text-container">
|
||||||
<span class="expression-text-outer source-text">
|
<span class="expression-text-outer source-text">
|
||||||
<span class="expression-current-indicator"></span>
|
<span class="expression-current-indicator"></span>
|
||||||
<span class="expression-text"></span>
|
<span class="expression-text"></span>
|
||||||
|
@ -24,7 +24,7 @@
|
|||||||
* The public properties and data should be backwards compatible.
|
* The public properties and data should be backwards compatible.
|
||||||
*/
|
*/
|
||||||
class AnkiNoteData {
|
class AnkiNoteData {
|
||||||
constructor({
|
constructor(japaneseUtil, marker, {
|
||||||
definition,
|
definition,
|
||||||
resultOutputMode,
|
resultOutputMode,
|
||||||
mode,
|
mode,
|
||||||
@ -32,7 +32,8 @@ class AnkiNoteData {
|
|||||||
compactTags,
|
compactTags,
|
||||||
context,
|
context,
|
||||||
injectedMedia=null
|
injectedMedia=null
|
||||||
}, marker) {
|
}) {
|
||||||
|
this._japaneseUtil = japaneseUtil;
|
||||||
this._definition = definition;
|
this._definition = definition;
|
||||||
this._resultOutputMode = resultOutputMode;
|
this._resultOutputMode = resultOutputMode;
|
||||||
this._mode = mode;
|
this._mode = mode;
|
||||||
@ -47,6 +48,7 @@ class AnkiNoteData {
|
|||||||
this._uniqueReadings = null;
|
this._uniqueReadings = null;
|
||||||
this._publicContext = null;
|
this._publicContext = null;
|
||||||
this._cloze = null;
|
this._cloze = null;
|
||||||
|
this._furiganaSegmentsCache = null;
|
||||||
|
|
||||||
this._prepareDefinition(definition, injectedMedia, context);
|
this._prepareDefinition(definition, injectedMedia, context);
|
||||||
}
|
}
|
||||||
@ -236,5 +238,47 @@ class AnkiNoteData {
|
|||||||
enumerable: true,
|
enumerable: true,
|
||||||
get: this._getClozeCached.bind(this)
|
get: this._getClozeCached.bind(this)
|
||||||
});
|
});
|
||||||
|
|
||||||
|
for (const definition2 of this._getAllDefinitions(definition)) {
|
||||||
|
if (definition2.type === 'term') {
|
||||||
|
this._defineFuriganaSegments(definition2);
|
||||||
|
}
|
||||||
|
for (const expression of definition2.expressions) {
|
||||||
|
this._defineFuriganaSegments(expression);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
_defineFuriganaSegments(object) {
|
||||||
|
Object.defineProperty(object, 'furiganaSegments', {
|
||||||
|
configurable: true,
|
||||||
|
enumerable: true,
|
||||||
|
get: this._getFuriganaSegments.bind(this, object)
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
_getFuriganaSegments(object) {
|
||||||
|
if (this._furiganaSegmentsCache !== null) {
|
||||||
|
const cachedResult = this._furiganaSegmentsCache.get(object);
|
||||||
|
if (typeof cachedResult !== 'undefined') { return cachedResult; }
|
||||||
|
} else {
|
||||||
|
this._furiganaSegmentsCache = new Map();
|
||||||
|
}
|
||||||
|
|
||||||
|
const {expression, reading} = object;
|
||||||
|
const result = this._japaneseUtil.distributeFurigana(expression, reading);
|
||||||
|
this._furiganaSegmentsCache.set(object, result);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
_getAllDefinitions(definition) {
|
||||||
|
const definitions = [definition];
|
||||||
|
for (let i = 0; i < definitions.length; ++i) {
|
||||||
|
const childDefinitions = definitions[i].definitions;
|
||||||
|
if (Array.isArray(childDefinitions)) {
|
||||||
|
definitions.push(...childDefinitions);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return definitions;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -190,11 +190,9 @@ class DisplayGenerator {
|
|||||||
disambiguationContainer.dataset[attribute] = value;
|
disambiguationContainer.dataset[attribute] = value;
|
||||||
}
|
}
|
||||||
for (const {expression, reading} of disambiguation) {
|
for (const {expression, reading} of disambiguation) {
|
||||||
const segments = this._japaneseUtil.distributeFurigana(expression, reading);
|
|
||||||
const disambiguationItem = document.createElement('span');
|
const disambiguationItem = document.createElement('span');
|
||||||
disambiguationItem.className = 'tag-details-disambiguation';
|
disambiguationItem.className = 'tag-details-disambiguation';
|
||||||
disambiguationItem.lang = 'ja';
|
this._appendFurigana(disambiguationItem, expression, reading, (container, text) => {
|
||||||
this._appendFurigana(disambiguationItem, segments, (container, text) => {
|
|
||||||
container.appendChild(document.createTextNode(text));
|
container.appendChild(document.createTextNode(text));
|
||||||
});
|
});
|
||||||
disambiguationContainer.appendChild(disambiguationItem);
|
disambiguationContainer.appendChild(disambiguationItem);
|
||||||
@ -232,7 +230,7 @@ class DisplayGenerator {
|
|||||||
// Private
|
// Private
|
||||||
|
|
||||||
_createTermExpression(details) {
|
_createTermExpression(details) {
|
||||||
const {termFrequency, furiganaSegments, expression, reading, termTags, pitches} = details;
|
const {termFrequency, expression, reading, termTags, pitches} = details;
|
||||||
|
|
||||||
const searchQueries = [];
|
const searchQueries = [];
|
||||||
if (expression) { searchQueries.push(expression); }
|
if (expression) { searchQueries.push(expression); }
|
||||||
@ -253,7 +251,7 @@ class DisplayGenerator {
|
|||||||
|
|
||||||
this._setTextContent(node.querySelector('.expression-reading'), reading);
|
this._setTextContent(node.querySelector('.expression-reading'), reading);
|
||||||
|
|
||||||
this._appendFurigana(expressionContainer, furiganaSegments, this._appendKanjiLinks.bind(this));
|
this._appendFurigana(expressionContainer, expression, reading, this._appendKanjiLinks.bind(this));
|
||||||
this._appendMultiple(tagContainer, this._createTag.bind(this), termTags);
|
this._appendMultiple(tagContainer, this._createTag.bind(this), termTags);
|
||||||
this._appendMultiple(tagContainer, this._createSearchTag.bind(this), searchQueries);
|
this._appendMultiple(tagContainer, this._createSearchTag.bind(this), searchQueries);
|
||||||
|
|
||||||
@ -651,7 +649,6 @@ class DisplayGenerator {
|
|||||||
}
|
}
|
||||||
|
|
||||||
_appendKanjiLinks(container, text) {
|
_appendKanjiLinks(container, text) {
|
||||||
container.lang = 'ja';
|
|
||||||
const jp = this._japaneseUtil;
|
const jp = this._japaneseUtil;
|
||||||
let part = '';
|
let part = '';
|
||||||
for (const c of text) {
|
for (const c of text) {
|
||||||
@ -692,7 +689,9 @@ class DisplayGenerator {
|
|||||||
return count;
|
return count;
|
||||||
}
|
}
|
||||||
|
|
||||||
_appendFurigana(container, segments, addText) {
|
_appendFurigana(container, expression, reading, addText) {
|
||||||
|
container.lang = 'ja';
|
||||||
|
const segments = this._japaneseUtil.distributeFurigana(expression, reading);
|
||||||
for (const {text, furigana} of segments) {
|
for (const {text, furigana} of segments) {
|
||||||
if (furigana) {
|
if (furigana) {
|
||||||
const ruby = document.createElement('ruby');
|
const ruby = document.createElement('ruby');
|
||||||
|
@ -1080,8 +1080,7 @@ class Translator {
|
|||||||
this._sortTags(definitionTagsExpanded);
|
this._sortTags(definitionTagsExpanded);
|
||||||
this._sortTags(termTagsExpanded);
|
this._sortTags(termTagsExpanded);
|
||||||
|
|
||||||
const furiganaSegments = this._japaneseUtil.distributeFurigana(expression, reading);
|
const termDetailsList = [this._createTermDetails(sourceTerm, expression, reading, termTagsExpanded)];
|
||||||
const termDetailsList = [this._createTermDetails(sourceTerm, expression, reading, furiganaSegments, termTagsExpanded)];
|
|
||||||
const sourceTermExactMatchCount = (sourceTerm === expression ? 1 : 0);
|
const sourceTermExactMatchCount = (sourceTerm === expression ? 1 : 0);
|
||||||
|
|
||||||
return {
|
return {
|
||||||
@ -1100,7 +1099,6 @@ class Translator {
|
|||||||
expression,
|
expression,
|
||||||
reading,
|
reading,
|
||||||
expressions: termDetailsList,
|
expressions: termDetailsList,
|
||||||
furiganaSegments,
|
|
||||||
glossary,
|
glossary,
|
||||||
definitionTags: definitionTagsExpanded,
|
definitionTags: definitionTagsExpanded,
|
||||||
termTags: termTagsExpanded,
|
termTags: termTagsExpanded,
|
||||||
@ -1118,12 +1116,12 @@ class Translator {
|
|||||||
* @returns A single 'termGrouped' definition.
|
* @returns A single 'termGrouped' definition.
|
||||||
*/
|
*/
|
||||||
_createGroupedTermDefinition(definitions) {
|
_createGroupedTermDefinition(definitions) {
|
||||||
const {reasons, source, rawSource, sourceTerm, expressions: [{expression, reading, furiganaSegments}]} = definitions[0];
|
const {reasons, source, rawSource, sourceTerm, expressions: [{expression, reading}]} = definitions[0];
|
||||||
const score = this._getMaxDefinitionScore(definitions);
|
const score = this._getMaxDefinitionScore(definitions);
|
||||||
const dictionaryOrder = this._getBestDictionaryOrder(definitions);
|
const dictionaryOrder = this._getBestDictionaryOrder(definitions);
|
||||||
const dictionaryNames = this._getUniqueDictionaryNames(definitions);
|
const dictionaryNames = this._getUniqueDictionaryNames(definitions);
|
||||||
const termTags = this._getUniqueTermTags(definitions);
|
const termTags = this._getUniqueTermTags(definitions);
|
||||||
const termDetailsList = [this._createTermDetails(sourceTerm, expression, reading, furiganaSegments, termTags)];
|
const termDetailsList = [this._createTermDetails(sourceTerm, expression, reading, termTags)];
|
||||||
const sourceTermExactMatchCount = (sourceTerm === expression ? 1 : 0);
|
const sourceTermExactMatchCount = (sourceTerm === expression ? 1 : 0);
|
||||||
return {
|
return {
|
||||||
type: 'termGrouped',
|
type: 'termGrouped',
|
||||||
@ -1141,7 +1139,6 @@ class Translator {
|
|||||||
expression,
|
expression,
|
||||||
reading,
|
reading,
|
||||||
expressions: termDetailsList,
|
expressions: termDetailsList,
|
||||||
furiganaSegments, // Contains duplicate data
|
|
||||||
// glossary
|
// glossary
|
||||||
// definitionTags
|
// definitionTags
|
||||||
termTags,
|
termTags,
|
||||||
@ -1173,7 +1170,6 @@ class Translator {
|
|||||||
expression: expressions,
|
expression: expressions,
|
||||||
reading: readings,
|
reading: readings,
|
||||||
expressions: termDetailsList,
|
expressions: termDetailsList,
|
||||||
// furiganaSegments
|
|
||||||
// glossary
|
// glossary
|
||||||
// definitionTags
|
// definitionTags
|
||||||
// termTags
|
// termTags
|
||||||
@ -1221,7 +1217,6 @@ class Translator {
|
|||||||
expression: [...expressions],
|
expression: [...expressions],
|
||||||
reading: [...readings],
|
reading: [...readings],
|
||||||
expressions: termDetailsList,
|
expressions: termDetailsList,
|
||||||
// furiganaSegments
|
|
||||||
glossary: [...glossary],
|
glossary: [...glossary],
|
||||||
definitionTags,
|
definitionTags,
|
||||||
// termTags
|
// termTags
|
||||||
@ -1240,7 +1235,7 @@ class Translator {
|
|||||||
*/
|
*/
|
||||||
_createTermDetailsList(definitions) {
|
_createTermDetailsList(definitions) {
|
||||||
const termInfoMap = new Map();
|
const termInfoMap = new Map();
|
||||||
for (const {expression, reading, sourceTerm, furiganaSegments, termTags} of definitions) {
|
for (const {expression, reading, sourceTerm, termTags} of definitions) {
|
||||||
let readingMap = termInfoMap.get(expression);
|
let readingMap = termInfoMap.get(expression);
|
||||||
if (typeof readingMap === 'undefined') {
|
if (typeof readingMap === 'undefined') {
|
||||||
readingMap = new Map();
|
readingMap = new Map();
|
||||||
@ -1251,7 +1246,6 @@ class Translator {
|
|||||||
if (typeof termInfo === 'undefined') {
|
if (typeof termInfo === 'undefined') {
|
||||||
termInfo = {
|
termInfo = {
|
||||||
sourceTerm,
|
sourceTerm,
|
||||||
furiganaSegments,
|
|
||||||
termTagsMap: new Map()
|
termTagsMap: new Map()
|
||||||
};
|
};
|
||||||
readingMap.set(reading, termInfo);
|
readingMap.set(reading, termInfo);
|
||||||
@ -1267,22 +1261,21 @@ class Translator {
|
|||||||
|
|
||||||
const termDetailsList = [];
|
const termDetailsList = [];
|
||||||
for (const [expression, readingMap] of termInfoMap.entries()) {
|
for (const [expression, readingMap] of termInfoMap.entries()) {
|
||||||
for (const [reading, {termTagsMap, sourceTerm, furiganaSegments}] of readingMap.entries()) {
|
for (const [reading, {termTagsMap, sourceTerm}] of readingMap.entries()) {
|
||||||
const termTags = [...termTagsMap.values()];
|
const termTags = [...termTagsMap.values()];
|
||||||
this._sortTags(termTags);
|
this._sortTags(termTags);
|
||||||
termDetailsList.push(this._createTermDetails(sourceTerm, expression, reading, furiganaSegments, termTags));
|
termDetailsList.push(this._createTermDetails(sourceTerm, expression, reading, termTags));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return termDetailsList;
|
return termDetailsList;
|
||||||
}
|
}
|
||||||
|
|
||||||
_createTermDetails(sourceTerm, expression, reading, furiganaSegments, termTags) {
|
_createTermDetails(sourceTerm, expression, reading, termTags) {
|
||||||
const termFrequency = this._scoreToTermFrequency(this._getTermTagsScoreSum(termTags));
|
const termFrequency = this._scoreToTermFrequency(this._getTermTagsScoreSum(termTags));
|
||||||
return {
|
return {
|
||||||
sourceTerm,
|
sourceTerm,
|
||||||
expression,
|
expression,
|
||||||
reading,
|
reading,
|
||||||
furiganaSegments, // Contains duplicate data
|
|
||||||
termTags,
|
termTags,
|
||||||
termFrequency,
|
termFrequency,
|
||||||
frequencies: [],
|
frequencies: [],
|
||||||
|
@ -26,7 +26,7 @@
|
|||||||
const japaneseUtil = new JapaneseUtil(null);
|
const japaneseUtil = new JapaneseUtil(null);
|
||||||
const templateRenderer = new TemplateRenderer(japaneseUtil);
|
const templateRenderer = new TemplateRenderer(japaneseUtil);
|
||||||
templateRenderer.registerDataType('ankiNote', {
|
templateRenderer.registerDataType('ankiNote', {
|
||||||
modifier: ({data, marker}) => new AnkiNoteData(data, marker).createPublic()
|
modifier: ({data, marker}) => new AnkiNoteData(japaneseUtil, marker, data).createPublic()
|
||||||
});
|
});
|
||||||
const templateRendererFrameApi = new TemplateRendererFrameApi(templateRenderer);
|
const templateRendererFrameApi = new TemplateRendererFrameApi(templateRenderer);
|
||||||
templateRendererFrameApi.prepare();
|
templateRendererFrameApi.prepare();
|
||||||
|
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue
Block a user