diff options
Diffstat (limited to 'ext/js/display')
| -rw-r--r-- | ext/js/display/display-anki.js | 4 | ||||
| -rw-r--r-- | ext/js/display/display-content-manager.js | 4 | ||||
| -rw-r--r-- | ext/js/display/display-generator.js | 26 | ||||
| -rw-r--r-- | ext/js/display/sandbox/pronunciation-generator.js | 378 | 
4 files changed, 204 insertions, 208 deletions
diff --git a/ext/js/display/display-anki.js b/ext/js/display/display-anki.js index 5433142d..68d28d33 100644 --- a/ext/js/display/display-anki.js +++ b/ext/js/display/display-anki.js @@ -20,7 +20,7 @@ import {EventListenerCollection} from '../core/event-listener-collection.js';  import {toError} from '../core/to-error.js';  import {deferPromise} from '../core/utilities.js';  import {AnkiNoteBuilder} from '../data/anki-note-builder.js'; -import {AnkiUtil} from '../data/anki-util.js'; +import {isNoteDataValid} from '../data/anki-util.js';  import {PopupMenu} from '../dom/popup-menu.js';  import {querySelectorNotNull} from '../dom/query-selector.js';  import {TemplateRendererProxy} from '../templates/template-renderer-proxy.js'; @@ -676,7 +676,7 @@ export class DisplayAnki {      _getAnkiNoteInfoForceValue(notes, canAdd) {          const results = [];          for (const note of notes) { -            const valid = AnkiUtil.isNoteDataValid(note); +            const valid = isNoteDataValid(note);              results.push({canAdd, valid, noteIds: null});          }          return results; diff --git a/ext/js/display/display-content-manager.js b/ext/js/display/display-content-manager.js index d13dffb3..4465ce3e 100644 --- a/ext/js/display/display-content-manager.js +++ b/ext/js/display/display-content-manager.js @@ -17,7 +17,7 @@   */  import {EventListenerCollection} from '../core/event-listener-collection.js'; -import {ArrayBufferUtil} from '../data/sandbox/array-buffer-util.js'; +import {base64ToArrayBuffer} from '../data/sandbox/array-buffer-util.js';  import {yomitan} from '../yomitan.js';  /** @@ -143,7 +143,7 @@ export class DisplayContentManager {          const datas = await yomitan.api.getMedia([{path, dictionary}]);          if (token === this._token && datas.length > 0) {              const data = datas[0]; -            const buffer = ArrayBufferUtil.base64ToArrayBuffer(data.content); +            const buffer = base64ToArrayBuffer(data.content);              const blob = new Blob([buffer], {type: data.mediaType});              const url = URL.createObjectURL(blob);              return {data, url}; diff --git a/ext/js/display/display-generator.js b/ext/js/display/display-generator.js index eef58bb0..01f6f38b 100644 --- a/ext/js/display/display-generator.js +++ b/ext/js/display/display-generator.js @@ -18,11 +18,11 @@  import {ExtensionError} from '../core/extension-error.js';  import {isObject} from '../core/utilities.js'; -import {DictionaryDataUtil} from '../dictionary/dictionary-data-util.js'; +import {getDisambiguations, getGroupedPronunciations, getTermFrequency, groupKanjiFrequencies, groupTermFrequencies, groupTermTags, isNonNounVerbOrAdjective} from '../dictionary/dictionary-data-util.js';  import {HtmlTemplateCollection} from '../dom/html-template-collection.js';  import {distributeFurigana, getKanaMorae, getPitchCategory, isCodePointKanji, isStringPartiallyJapanese} from '../language/japanese.js';  import {yomitan} from '../yomitan.js'; -import {PronunciationGenerator} from './sandbox/pronunciation-generator.js'; +import {createPronunciationDownstepPosition, createPronunciationGraph, createPronunciationText} from './sandbox/pronunciation-generator.js';  import {StructuredContentGenerator} from './sandbox/structured-content-generator.js';  export class DisplayGenerator { @@ -38,8 +38,6 @@ export class DisplayGenerator {          this._templates = new HtmlTemplateCollection();          /** @type {StructuredContentGenerator} */          this._structuredContentGenerator = new StructuredContentGenerator(this._contentManager, document); -        /** @type {PronunciationGenerator} */ -        this._pronunciationGenerator = new PronunciationGenerator();      }      /** */ @@ -73,10 +71,10 @@ export class DisplayGenerator {          const headwordTagsContainer = this._querySelector(node, '.headword-list-tag-list');          const {headwords, type, inflectionRuleChainCandidates, definitions, frequencies, pronunciations} = dictionaryEntry; -        const groupedPronunciations = DictionaryDataUtil.getGroupedPronunciations(dictionaryEntry); +        const groupedPronunciations = getGroupedPronunciations(dictionaryEntry);          const pronunciationCount = groupedPronunciations.reduce((i, v) => i + v.pronunciations.length, 0); -        const groupedFrequencies = DictionaryDataUtil.groupTermFrequencies(dictionaryEntry); -        const termTags = DictionaryDataUtil.groupTermTags(dictionaryEntry); +        const groupedFrequencies = groupTermFrequencies(dictionaryEntry); +        const termTags = groupTermTags(dictionaryEntry);          /** @type {Set<string>} */          const uniqueTerms = new Set(); @@ -166,7 +164,7 @@ export class DisplayGenerator {          const dictionaryIndicesContainer = this._querySelector(node, '.kanji-dictionary-indices');          this._setTextContent(glyphContainer, dictionaryEntry.character, 'ja'); -        const groupedFrequencies = DictionaryDataUtil.groupKanjiFrequencies(dictionaryEntry.frequencies); +        const groupedFrequencies = groupKanjiFrequencies(dictionaryEntry.frequencies);          const dictionaryTag = this._createDictionaryTag(dictionaryEntry.dictionary); @@ -334,7 +332,7 @@ export class DisplayGenerator {          node.dataset.isPrimary = `${isPrimaryAny}`;          node.dataset.readingIsSame = `${reading === term}`; -        node.dataset.frequency = DictionaryDataUtil.getTermFrequency(tags); +        node.dataset.frequency = getTermFrequency(tags);          node.dataset.matchTypes = [...matchTypes].join(' ');          node.dataset.matchSources = [...matchSources].join(' '); @@ -415,7 +413,7 @@ export class DisplayGenerator {       */      _createTermDefinition(definition, dictionaryTag, headwords, uniqueTerms, uniqueReadings) {          const {dictionary, tags, headwordIndices, entries} = definition; -        const disambiguations = DictionaryDataUtil.getDisambiguations(headwords, headwordIndices, uniqueTerms, uniqueReadings); +        const disambiguations = getDisambiguations(headwords, headwordIndices, uniqueTerms, uniqueReadings);          const node = this._instantiate('definition-item'); @@ -742,15 +740,15 @@ export class DisplayGenerator {          this._createPronunciationDisambiguations(n, exclusiveTerms, exclusiveReadings);          n = this._querySelector(node, '.pronunciation-downstep-notation-container'); -        n.appendChild(this._pronunciationGenerator.createPronunciationDownstepPosition(position)); +        n.appendChild(createPronunciationDownstepPosition(position));          n = this._querySelector(node, '.pronunciation-text-container');          n.lang = 'ja'; -        n.appendChild(this._pronunciationGenerator.createPronunciationText(morae, position, nasalPositions, devoicePositions)); +        n.appendChild(createPronunciationText(morae, position, nasalPositions, devoicePositions));          n = this._querySelector(node, '.pronunciation-graph-container'); -        n.appendChild(this._pronunciationGenerator.createPronunciationGraph(morae, position)); +        n.appendChild(createPronunciationGraph(morae, position));          return node;      } @@ -1040,7 +1038,7 @@ export class DisplayGenerator {       */      _getPronunciationCategories(reading, termPronunciations, wordClasses, headwordIndex) {          if (termPronunciations.length === 0) { return null; } -        const isVerbOrAdjective = DictionaryDataUtil.isNonNounVerbOrAdjective(wordClasses); +        const isVerbOrAdjective = isNonNounVerbOrAdjective(wordClasses);          /** @type {Set<import('japanese-util').PitchCategory>} */          const categories = new Set();          for (const termPronunciation of termPronunciations) { diff --git a/ext/js/display/sandbox/pronunciation-generator.js b/ext/js/display/sandbox/pronunciation-generator.js index 45631e74..373ec830 100644 --- a/ext/js/display/sandbox/pronunciation-generator.js +++ b/ext/js/display/sandbox/pronunciation-generator.js @@ -18,221 +18,219 @@  import {getKanaDiacriticInfo, isMoraPitchHigh} from '../../language/japanese.js'; -export class PronunciationGenerator { -    /** -     * @param {string[]} morae -     * @param {number} downstepPosition -     * @param {number[]} nasalPositions -     * @param {number[]} devoicePositions -     * @returns {HTMLSpanElement} -     */ -    createPronunciationText(morae, downstepPosition, nasalPositions, devoicePositions) { -        const nasalPositionsSet = nasalPositions.length > 0 ? new Set(nasalPositions) : null; -        const devoicePositionsSet = devoicePositions.length > 0 ? new Set(devoicePositions) : null; -        const container = document.createElement('span'); -        container.className = 'pronunciation-text'; -        for (let i = 0, ii = morae.length; i < ii; ++i) { -            const i1 = i + 1; -            const mora = morae[i]; -            const highPitch = isMoraPitchHigh(i, downstepPosition); -            const highPitchNext = isMoraPitchHigh(i1, downstepPosition); -            const nasal = nasalPositionsSet !== null && nasalPositionsSet.has(i1); -            const devoice = devoicePositionsSet !== null && devoicePositionsSet.has(i1); - -            const n1 = document.createElement('span'); -            n1.className = 'pronunciation-mora'; -            n1.dataset.position = `${i}`; -            n1.dataset.pitch = highPitch ? 'high' : 'low'; -            n1.dataset.pitchNext = highPitchNext ? 'high' : 'low'; - -            const characterNodes = []; -            for (const character of mora) { -                const n2 = document.createElement('span'); -                n2.className = 'pronunciation-character'; -                n2.textContent = character; -                n1.appendChild(n2); -                characterNodes.push(n2); -            } - -            if (devoice) { -                n1.dataset.devoice = 'true'; -                const n3 = document.createElement('span'); -                n3.className = 'pronunciation-devoice-indicator'; -                n1.appendChild(n3); -            } -            if (nasal && characterNodes.length > 0) { -                n1.dataset.nasal = 'true'; - -                const group = document.createElement('span'); -                group.className = 'pronunciation-character-group'; +/** + * @param {string[]} morae + * @param {number} downstepPosition + * @param {number[]} nasalPositions + * @param {number[]} devoicePositions + * @returns {HTMLSpanElement} + */ +export function createPronunciationText(morae, downstepPosition, nasalPositions, devoicePositions) { +    const nasalPositionsSet = nasalPositions.length > 0 ? new Set(nasalPositions) : null; +    const devoicePositionsSet = devoicePositions.length > 0 ? new Set(devoicePositions) : null; +    const container = document.createElement('span'); +    container.className = 'pronunciation-text'; +    for (let i = 0, ii = morae.length; i < ii; ++i) { +        const i1 = i + 1; +        const mora = morae[i]; +        const highPitch = isMoraPitchHigh(i, downstepPosition); +        const highPitchNext = isMoraPitchHigh(i1, downstepPosition); +        const nasal = nasalPositionsSet !== null && nasalPositionsSet.has(i1); +        const devoice = devoicePositionsSet !== null && devoicePositionsSet.has(i1); -                const n2 = characterNodes[0]; -                const character = /** @type {string} */ (n2.textContent); +        const n1 = document.createElement('span'); +        n1.className = 'pronunciation-mora'; +        n1.dataset.position = `${i}`; +        n1.dataset.pitch = highPitch ? 'high' : 'low'; +        n1.dataset.pitchNext = highPitchNext ? 'high' : 'low'; + +        const characterNodes = []; +        for (const character of mora) { +            const n2 = document.createElement('span'); +            n2.className = 'pronunciation-character'; +            n2.textContent = character; +            n1.appendChild(n2); +            characterNodes.push(n2); +        } -                const characterInfo = getKanaDiacriticInfo(character); -                if (characterInfo !== null) { -                    n1.dataset.originalText = mora; -                    n2.dataset.originalText = character; -                    n2.textContent = characterInfo.character; -                } +        if (devoice) { +            n1.dataset.devoice = 'true'; +            const n3 = document.createElement('span'); +            n3.className = 'pronunciation-devoice-indicator'; +            n1.appendChild(n3); +        } +        if (nasal && characterNodes.length > 0) { +            n1.dataset.nasal = 'true'; -                let n3 = document.createElement('span'); -                n3.className = 'pronunciation-nasal-diacritic'; -                n3.textContent = '\u309a'; // Combining handakuten -                group.appendChild(n3); +            const group = document.createElement('span'); +            group.className = 'pronunciation-character-group'; -                n3 = document.createElement('span'); -                n3.className = 'pronunciation-nasal-indicator'; -                group.appendChild(n3); +            const n2 = characterNodes[0]; +            const character = /** @type {string} */ (n2.textContent); -                /** @type {ParentNode} */ (n2.parentNode).replaceChild(group, n2); -                group.insertBefore(n2, group.firstChild); +            const characterInfo = getKanaDiacriticInfo(character); +            if (characterInfo !== null) { +                n1.dataset.originalText = mora; +                n2.dataset.originalText = character; +                n2.textContent = characterInfo.character;              } -            const line = document.createElement('span'); -            line.className = 'pronunciation-mora-line'; -            n1.appendChild(line); +            let n3 = document.createElement('span'); +            n3.className = 'pronunciation-nasal-diacritic'; +            n3.textContent = '\u309a'; // Combining handakuten +            group.appendChild(n3); -            container.appendChild(n1); -        } -        return container; -    } +            n3 = document.createElement('span'); +            n3.className = 'pronunciation-nasal-indicator'; +            group.appendChild(n3); -    /** -     * @param {string[]} morae -     * @param {number} downstepPosition -     * @returns {SVGSVGElement} -     */ -    createPronunciationGraph(morae, downstepPosition) { -        const ii = morae.length; - -        const svgns = 'http://www.w3.org/2000/svg'; -        const svg = document.createElementNS(svgns, 'svg'); -        svg.setAttribute('xmlns', svgns); -        svg.setAttribute('class', 'pronunciation-graph'); -        svg.setAttribute('focusable', 'false'); -        svg.setAttribute('viewBox', `0 0 ${50 * (ii + 1)} 100`); - -        if (ii <= 0) { return svg; } - -        const path1 = document.createElementNS(svgns, 'path'); -        svg.appendChild(path1); - -        const path2 = document.createElementNS(svgns, 'path'); -        svg.appendChild(path2); - -        const pathPoints = []; -        for (let i = 0; i < ii; ++i) { -            const highPitch = isMoraPitchHigh(i, downstepPosition); -            const highPitchNext = isMoraPitchHigh(i + 1, downstepPosition); -            const x = i * 50 + 25; -            const y = highPitch ? 25 : 75; -            if (highPitch && !highPitchNext) { -                this._addGraphDotDownstep(svg, svgns, x, y); -            } else { -                this._addGraphDot(svg, svgns, x, y); -            } -            pathPoints.push(`${x} ${y}`); +            /** @type {ParentNode} */ (n2.parentNode).replaceChild(group, n2); +            group.insertBefore(n2, group.firstChild);          } -        path1.setAttribute('class', 'pronunciation-graph-line'); -        path1.setAttribute('d', `M${pathPoints.join(' L')}`); +        const line = document.createElement('span'); +        line.className = 'pronunciation-mora-line'; +        n1.appendChild(line); + +        container.appendChild(n1); +    } +    return container; +} -        pathPoints.splice(0, ii - 1); -        { -            const highPitch = isMoraPitchHigh(ii, downstepPosition); -            const x = ii * 50 + 25; -            const y = highPitch ? 25 : 75; -            this._addGraphTriangle(svg, svgns, x, y); -            pathPoints.push(`${x} ${y}`); +/** + * @param {string[]} morae + * @param {number} downstepPosition + * @returns {SVGSVGElement} + */ +export function createPronunciationGraph(morae, downstepPosition) { +    const ii = morae.length; + +    const svgns = 'http://www.w3.org/2000/svg'; +    const svg = document.createElementNS(svgns, 'svg'); +    svg.setAttribute('xmlns', svgns); +    svg.setAttribute('class', 'pronunciation-graph'); +    svg.setAttribute('focusable', 'false'); +    svg.setAttribute('viewBox', `0 0 ${50 * (ii + 1)} 100`); + +    if (ii <= 0) { return svg; } + +    const path1 = document.createElementNS(svgns, 'path'); +    svg.appendChild(path1); + +    const path2 = document.createElementNS(svgns, 'path'); +    svg.appendChild(path2); + +    const pathPoints = []; +    for (let i = 0; i < ii; ++i) { +        const highPitch = isMoraPitchHigh(i, downstepPosition); +        const highPitchNext = isMoraPitchHigh(i + 1, downstepPosition); +        const x = i * 50 + 25; +        const y = highPitch ? 25 : 75; +        if (highPitch && !highPitchNext) { +            addGraphDotDownstep(svg, svgns, x, y); +        } else { +            addGraphDot(svg, svgns, x, y);          } +        pathPoints.push(`${x} ${y}`); +    } -        path2.setAttribute('class', 'pronunciation-graph-line-tail'); -        path2.setAttribute('d', `M${pathPoints.join(' L')}`); +    path1.setAttribute('class', 'pronunciation-graph-line'); +    path1.setAttribute('d', `M${pathPoints.join(' L')}`); -        return svg; +    pathPoints.splice(0, ii - 1); +    { +        const highPitch = isMoraPitchHigh(ii, downstepPosition); +        const x = ii * 50 + 25; +        const y = highPitch ? 25 : 75; +        addGraphTriangle(svg, svgns, x, y); +        pathPoints.push(`${x} ${y}`);      } -    /** -     * @param {number} downstepPosition -     * @returns {HTMLSpanElement} -     */ -    createPronunciationDownstepPosition(downstepPosition) { -        const downstepPositionString = `${downstepPosition}`; +    path2.setAttribute('class', 'pronunciation-graph-line-tail'); +    path2.setAttribute('d', `M${pathPoints.join(' L')}`); -        const n1 = document.createElement('span'); -        n1.className = 'pronunciation-downstep-notation'; -        n1.dataset.downstepPosition = downstepPositionString; +    return svg; +} -        let n2 = document.createElement('span'); -        n2.className = 'pronunciation-downstep-notation-prefix'; -        n2.textContent = '['; -        n1.appendChild(n2); +/** + * @param {number} downstepPosition + * @returns {HTMLSpanElement} + */ +export function createPronunciationDownstepPosition(downstepPosition) { +    const downstepPositionString = `${downstepPosition}`; -        n2 = document.createElement('span'); -        n2.className = 'pronunciation-downstep-notation-number'; -        n2.textContent = downstepPositionString; -        n1.appendChild(n2); +    const n1 = document.createElement('span'); +    n1.className = 'pronunciation-downstep-notation'; +    n1.dataset.downstepPosition = downstepPositionString; -        n2 = document.createElement('span'); -        n2.className = 'pronunciation-downstep-notation-suffix'; -        n2.textContent = ']'; -        n1.appendChild(n2); +    let n2 = document.createElement('span'); +    n2.className = 'pronunciation-downstep-notation-prefix'; +    n2.textContent = '['; +    n1.appendChild(n2); -        return n1; -    } +    n2 = document.createElement('span'); +    n2.className = 'pronunciation-downstep-notation-number'; +    n2.textContent = downstepPositionString; +    n1.appendChild(n2); -    // Private +    n2 = document.createElement('span'); +    n2.className = 'pronunciation-downstep-notation-suffix'; +    n2.textContent = ']'; +    n1.appendChild(n2); -    /** -     * @param {Element} container -     * @param {string} svgns -     * @param {number} x -     * @param {number} y -     */ -    _addGraphDot(container, svgns, x, y) { -        container.appendChild(this._createGraphCircle(svgns, 'pronunciation-graph-dot', x, y, '15')); -    } +    return n1; +} -    /** -     * @param {Element} container -     * @param {string} svgns -     * @param {number} x -     * @param {number} y -     */ -    _addGraphDotDownstep(container, svgns, x, y) { -        container.appendChild(this._createGraphCircle(svgns, 'pronunciation-graph-dot-downstep1', x, y, '15')); -        container.appendChild(this._createGraphCircle(svgns, 'pronunciation-graph-dot-downstep2', x, y, '5')); -    } +// Private -    /** -     * @param {Element} container -     * @param {string} svgns -     * @param {number} x -     * @param {number} y -     */ -    _addGraphTriangle(container, svgns, x, y) { -        const node = document.createElementNS(svgns, 'path'); -        node.setAttribute('class', 'pronunciation-graph-triangle'); -        node.setAttribute('d', 'M0 13 L15 -13 L-15 -13 Z'); -        node.setAttribute('transform', `translate(${x},${y})`); -        container.appendChild(node); -    } +/** + * @param {Element} container + * @param {string} svgns + * @param {number} x + * @param {number} y + */ +function addGraphDot(container, svgns, x, y) { +    container.appendChild(createGraphCircle(svgns, 'pronunciation-graph-dot', x, y, '15')); +} -    /** -     * @param {string} svgns -     * @param {string} className -     * @param {number} x -     * @param {number} y -     * @param {string} radius -     * @returns {Element} -     */ -    _createGraphCircle(svgns, className, x, y, radius) { -        const node = document.createElementNS(svgns, 'circle'); -        node.setAttribute('class', className); -        node.setAttribute('cx', `${x}`); -        node.setAttribute('cy', `${y}`); -        node.setAttribute('r', radius); -        return node; -    } +/** + * @param {Element} container + * @param {string} svgns + * @param {number} x + * @param {number} y + */ +function addGraphDotDownstep(container, svgns, x, y) { +    container.appendChild(createGraphCircle(svgns, 'pronunciation-graph-dot-downstep1', x, y, '15')); +    container.appendChild(createGraphCircle(svgns, 'pronunciation-graph-dot-downstep2', x, y, '5')); +} + +/** + * @param {Element} container + * @param {string} svgns + * @param {number} x + * @param {number} y + */ +function addGraphTriangle(container, svgns, x, y) { +    const node = document.createElementNS(svgns, 'path'); +    node.setAttribute('class', 'pronunciation-graph-triangle'); +    node.setAttribute('d', 'M0 13 L15 -13 L-15 -13 Z'); +    node.setAttribute('transform', `translate(${x},${y})`); +    container.appendChild(node); +} + +/** + * @param {string} svgns + * @param {string} className + * @param {number} x + * @param {number} y + * @param {string} radius + * @returns {Element} + */ +function createGraphCircle(svgns, className, x, y, radius) { +    const node = document.createElementNS(svgns, 'circle'); +    node.setAttribute('class', className); +    node.setAttribute('cx', `${x}`); +    node.setAttribute('cy', `${y}`); +    node.setAttribute('r', radius); +    return node;  }  |