diff options
Diffstat (limited to 'ext/mixed')
| -rw-r--r-- | ext/mixed/css/display.css | 153 | ||||
| -rw-r--r-- | ext/mixed/display-templates.html | 58 | ||||
| -rw-r--r-- | ext/mixed/js/dictionary-data-util.js | 55 | ||||
| -rw-r--r-- | ext/mixed/js/display-generator.js | 72 | 
4 files changed, 235 insertions, 103 deletions
| diff --git a/ext/mixed/css/display.css b/ext/mixed/css/display.css index 0e4b2012..fd320904 100644 --- a/ext/mixed/css/display.css +++ b/ext/mixed/css/display.css @@ -249,6 +249,12 @@ h3 {      margin: 0.25em 0 0.375em;      padding: 0;  } +h5 { +    font-size: calc(12em / 14); +    margin: 0; +    padding: 0; +    font-weight: normal; +}  a {      color: var(--link-color);      text-decoration: underline; @@ -693,27 +699,6 @@ button.action-button[data-icon=source-term]::before {  .tag-inner {      display: block;  } -.tag-frequency-separator::before { -    content: ':'; -} -.tag-frequency-disambiguation-separator::before { -    content: ':'; -} -.tag-frequency-disambiguation::before { -    content: '('; -} -.tag-frequency-disambiguation::after { -    content: ') '; -} -.frequencies .tag[data-reading-is-same=true] .tag-frequency-disambiguation-separator, -.frequencies .tag[data-reading-is-same=true] .tag-frequency-disambiguation-reading, -.entry[data-unique-expression-count='1'] .tag-frequency-disambiguation-separator, -.entry[data-unique-expression-count='1'] .tag-frequency-disambiguation-expression, -.entry[data-unique-reading-count='1'] .tag-frequency-disambiguation-separator, -.entry[data-unique-reading-count='1'] .tag-frequency-disambiguation-reading, -.entry[data-unique-expression-count='1'][data-unique-reading-count='1'] .tag-frequency-disambiguation { -    display: none; -}  /* Entries */ @@ -949,16 +934,6 @@ button.action-button[data-icon=source-term]::before {      bottom: -0.5em;      white-space: nowrap;  } -.entry[data-expression-multi=true] .term-expression-list .term-expression-details>.frequencies { -    display: block; -    position: absolute; -    left: 0; -    bottom: -1.9em; -    white-space: nowrap; -} -.entry[data-expression-multi=true] .term-expression-list .term-expression-details>.frequencies .tag-frequency-disambiguation { -    display: none; -}  /* Definitions */ @@ -1008,24 +983,106 @@ button.action-button[data-icon=source-term]::before {      opacity: 0;      white-space: pre-wrap;  } -.term-special-tags>.frequencies { -    display: inline; +.entry-body { +    margin-top: -0.5em; +} +.entry-body-section { +    margin-top: 0.5em; +} +.entry[data-definition-count='0'] .entry-body-section[data-section-type=definitions], +.entry[data-frequency-count='0'] .entry-body-section[data-section-type=frequencies], +.entry[data-pitch-accent-count='0'] .entry-body-section[data-section-type=pitch-accents] { +    display: none;  } -.term-entry-body[data-section-count='0'] .term-entry-body-section-header, -.term-entry-body[data-section-count='1'] .term-entry-body-section-header { +.entry[data-pitch-accent-count='0'][data-frequency-count='0'] .entry-body-section[data-section-type=definitions]>h5 {      display: none;  } -/* Pitch accent styles */ -.entry[data-pitch-accent-count='0'] .term-pitch-accent-container { +/* Frequencies */ +.frequency-group-list { +    margin: 0; +    padding: 0 0 0 var(--list-padding1); +    list-style-type: decimal; +} +.frequency-group-list[data-count='0'], +.frequency-group-list[data-count='1'] { +    padding-left: 0; +    list-style-type: none; +} +.frequency-list { +    margin: 0; +    padding: 0 0 0 var(--list-padding2); +    list-style-type: circle; +} +.frequency-list[data-count='0'], +.frequency-list[data-count='1'] { +    padding-left: 0; +    list-style-type: none; +} +.frequency-group-item::marker, +.frequency-item::marker { +    color: var(--text-color-light); +} +.frequency-disambiguation { +    color: var(--text-color-light); +} +.frequency-separator::before { +    content: ''; +} +.frequency-disambiguation-separator::before { +    content: ':'; +} +.frequency-disambiguation::before { +    content: '('; +} +.frequency-disambiguation::after { +    content: ' only) '; +} +.entry[data-unique-expression-count='1'] .frequency-item[data-has-reading=false] .frequency-disambiguation, +.entry[data-unique-reading-count='1'][data-unique-expression-count='1'] .frequency-disambiguation, +.frequency-item[data-reading-is-same=true] .frequency-disambiguation-separator, +.frequency-item[data-reading-is-same=true] .frequency-disambiguation-reading, +.frequency-item[data-has-reading=false] .frequency-disambiguation-separator, +.frequency-item[data-has-reading=false] .frequency-disambiguation-reading, +.entry[data-unique-expression-count='1'] .frequency-disambiguation-separator, +.entry[data-unique-expression-count='1'] .frequency-disambiguation-expression, +.entry[data-unique-reading-count='1'] .frequency-disambiguation-separator, +.entry[data-unique-reading-count='1'] .frequency-disambiguation-reading {      display: none;  } -.term-pitch-accent-container { -    border-bottom: var(--thin-border-size) solid var(--light-border-color); -    padding-bottom: 0.25em; -    margin-bottom: 0.25em; +:root[data-glossary-layout-mode=compact] .frequency-group-list, +:root[data-glossary-layout-mode=compact] .frequency-list, +.frequency-list[data-count='1'] { +    display: inline; +    list-style: none; +    padding-left: 0; +} +:root[data-glossary-layout-mode=compact] .frequency-group-item { +    display: inline-block; +    margin-right: 1em; +} +:root[data-glossary-layout-mode=compact] .entry-body-section[data-section-type=frequencies] { +    margin-right: -1em; +} +:root[data-glossary-layout-mode=compact] .frequency-item, +.frequency-list[data-count='1'] .frequency-item { +    display: inline-block; +} +:root[data-glossary-layout-mode=compact] .frequency-item:not(:first-child)::before, +.frequency-list[data-count='1'] .frequency-item:not(:first-child)::before { +    white-space: pre-wrap; +    content: var(--compact-list-separator); +    display: inline; +    color: var(--text-color-light);  } +:root[data-glossary-layout-mode=compact] .frequency-tag-list, +.frequency-group-item[data-count='1'] .frequency-tag-list { +    display: inline; +} + + +/* Pitch accent styles */  .term-pitch-accent-group-list {      margin: 0;      padding: 0 0 0 var(--list-padding1); @@ -1582,17 +1639,15 @@ button.footer-notification-close-button:active {      display: inline;      color: var(--text-color-light);  } -:root[data-glossary-layout-mode=compact] .entry:not([data-expression-multi=true]) .term-special-tags { + +:root[data-glossary-layout-mode=compact] .entry-body-section>h5 {      display: none;  } -:root[data-glossary-layout-mode=compact] .term-expression-details>.frequencies { -    display: inline; +:root[data-glossary-layout-mode=compact] .entry-body { +    margin-top: 0;  } - -:root[data-glossary-layout-mode=compact] .term-pitch-accent-container { -    border-bottom: none; -    padding-bottom: 0; -    margin-bottom: 0; +:root[data-glossary-layout-mode=compact] .entry-body-section { +    margin-top: 0;  }  :root[data-show-pitch-accent-downstep-notation=true] .term-pitch-accent-disambiguation-list[data-expression-count='0'],  :root[data-show-pitch-accent-downstep-notation=true] .term-pitch-accent-disambiguation[data-type=reading] { diff --git a/ext/mixed/display-templates.html b/ext/mixed/display-templates.html index 95432ad2..ac42e138 100644 --- a/ext/mixed/display-templates.html +++ b/ext/mixed/display-templates.html @@ -17,11 +17,20 @@              </div>              <div class="term-reasons"></div>          </div> -        <div class="term-special-tags"><div class="frequencies tag-list"></div></div>      </div> -    <div class="term-entry-body"> -        <div class="term-entry-body-section term-pitch-accent-container"><ol class="term-entry-body-section-content term-pitch-accent-group-list"></ol></div> -        <div class="term-entry-body-section term-definition-container"><ol class="term-entry-body-section-content term-definition-list"></ol></div> +    <div class="entry-body"> +        <div class="entry-body-section" data-section-type="frequencies"> +            <h5>Frequencies</h5> +            <ol class="entry-body-section-content frequency-group-list"></ol> +        </div> +        <div class="entry-body-section" data-section-type="pitch-accents"> +            <h5>Pitch Accents</h5> +            <ol class="entry-body-section-content term-pitch-accent-group-list"></ol> +        </div> +        <div class="entry-body-section" data-section-type="definitions"> +            <h5>Definitions</h5> +            <ol class="entry-body-section-content term-definition-list"></ol> +        </div>      </div>      <div class="debug-info"><a class="debug-log-link">Log debug info to console</a></div>  </div></template> @@ -34,7 +43,6 @@      <div class="term-expression-details">          <button class="action-button action-play-audio" data-icon="play-audio" title="Play audio"></button>          <div class="tags tag-list"></div> -        <div class="frequencies tag-list"></div>      </div>  </div></template>  <template id="term-definition-item-template"><li class="term-definition-item"><div class="term-definition-tag-list tag-list"></div><div class="term-definition-disambiguation-list"></div><ul class="term-glossary-list"></ul></li></template> @@ -43,6 +51,21 @@  <template id="term-glossary-item-image-template"><li class="term-glossary-item click-scannable" data-has-image="true"><span class="term-glossary-separator"> </span><span class="term-glossary"><a class="term-glossary-image-link" target="_blank" rel="noreferrer noopener"><span class="term-glossary-image-container"><span class="term-glossary-image-aspect-ratio-sizer"></span><img class="term-glossary-image" alt="" /><span class="term-glossary-image-container-overlay"></span></span><span class="term-glossary-image-link-text">Image</span></a> <span class="term-glossary-image-description"></span></span></li></template>  <template id="term-reason-template"><span class="term-reason"></span><span class="term-reason-separator"> </span></template> +<!-- Frequency templates --> +<template id="frequency-group-item-template"><li class="frequency-group-item"><div class="frequency-tag-list tag-list"></div><ul class="frequency-list"></ul></li></template> +<template id="term-frequency-item-template" data-remove-whitespace-text="true"><li class="frequency-item" data-frequency-type="term"> +    <span class="frequency-disambiguation"> +        <span class="frequency-disambiguation-expression"></span> +        <span class="frequency-disambiguation-separator"></span> +        <span class="frequency-disambiguation-reading"></span> +    </span> +    <span class="frequency-separator"></span> +    <span class="frequency-value"></span> +</li></template> +<template id="kanji-frequency-item-template" data-remove-whitespace-text="true"><li class="frequency-item" data-frequency-type="kanji"> +    <span class="frequency-value"></span> +</li></template> +  <!-- Pitch accent templates -->  <template id="term-pitch-accent-static-template"><svg xmlns="http://www.w3.org/2000/svg" style="display: none;">      <defs> @@ -73,9 +96,13 @@                  </div>              </div>          </div> -        <div class="frequencies"></div>      </div>      <div class="tags tag-list"></div> +    <div class="entry-body"> +        <div class="entry-body-section" data-section-type="frequencies"> +            <ol class="entry-body-section-content frequency-group-list"></ol> +        </div> +    </div>      <table class="kanji-glyph-data"><tbody>          <tr>              <th>Glossary</th> @@ -104,25 +131,6 @@  <!-- Tag templates -->  <template id="tag-template"><span class="tag"><span class="tag-inner"></span></span></template> -<template id="term-tag-frequency-template" data-remove-whitespace-text="true"><span class="tag" data-category="frequency"> -    <span class="tag-inner"> -        <span class="tag-frequency-disambiguation"> -            <span class="tag-frequency-disambiguation-expression"></span> -            <span class="tag-frequency-disambiguation-separator"></span> -            <span class="tag-frequency-disambiguation-reading"></span> -        </span> -        <span class="tag-frequency-dictionary-name"></span> -        <span class="tag-frequency-separator"></span> -        <span class="tag-frequency-value"></span> -    </span> -</span></template> -<template id="kanji-tag-frequency-template" data-remove-whitespace-text="true"><span class="tag" data-category="frequency"> -    <span class="tag-inner"> -        <span class="tag-frequency-dictionary-name"></span> -        <span class="tag-frequency-separator"></span> -        <span class="tag-frequency-value"></span> -    </span> -</span></template>  <!-- Extra -->  <template id="footer-notification-template"><div class="footer-notification"> diff --git a/ext/mixed/js/dictionary-data-util.js b/ext/mixed/js/dictionary-data-util.js index 8d8772fe..1e82ef63 100644 --- a/ext/mixed/js/dictionary-data-util.js +++ b/ext/mixed/js/dictionary-data-util.js @@ -16,6 +16,48 @@   */  class DictionaryDataUtil { +    static groupTermFrequencies(frequencies) { +        const map1 = new Map(); +        for (const {dictionary, expression, reading, hasReading, frequency} of frequencies) { +            let map2 = map1.get(dictionary); +            if (typeof map2 === 'undefined') { +                map2 = new Map(); +                map1.set(dictionary, map2); +            } + +            const readingKey = hasReading ? reading : null; +            const key = JSON.stringify([expression, readingKey], null, 0); +            let frequencyData = map2.get(key); +            if (typeof frequencyData === 'undefined') { +                frequencyData = {expression, reading: readingKey, frequencies: new Set()}; +                map2.set(key, frequencyData); +            } + +            frequencyData.frequencies.add(frequency); +        } +        return this._createFrequencyGroupsFromMap(map1); +    } + +    static groupKanjiFrequencies(frequencies) { +        const map1 = new Map(); +        for (const {dictionary, character, frequency} of frequencies) { +            let map2 = map1.get(dictionary); +            if (typeof map2 === 'undefined') { +                map2 = new Map(); +                map1.set(dictionary, map2); +            } + +            let frequencyData = map2.get(character); +            if (typeof frequencyData === 'undefined') { +                frequencyData = {character, frequencies: new Set()}; +                map2.set(character, frequencyData); +            } + +            frequencyData.frequencies.add(frequency); +        } +        return this._createFrequencyGroupsFromMap(map1); +    } +      static getPitchAccentInfos(definition) {          if (definition.type === 'kanji') { return []; } @@ -73,6 +115,19 @@ class DictionaryDataUtil {      // Private +    static _createFrequencyGroupsFromMap(map) { +        const results = []; +        for (const [dictionary, map2] of map.entries()) { +            const frequencyDataArray = []; +            for (const frequencyData of map2.values()) { +                frequencyData.frequencies = [...frequencyData.frequencies]; +                frequencyDataArray.push(frequencyData); +            } +            results.push({dictionary, frequencyData: frequencyDataArray}); +        } +        return results; +    } +      static _findExistingPitchAccentInfo(reading, position, tags, pitchAccentInfoList) {          for (const pitchInfo of pitchAccentInfoList) {              if ( diff --git a/ext/mixed/js/display-generator.js b/ext/mixed/js/display-generator.js index 6a8c03e3..a47a65ee 100644 --- a/ext/mixed/js/display-generator.js +++ b/ext/mixed/js/display-generator.js @@ -47,15 +47,15 @@ class DisplayGenerator {          const expressionsContainer = node.querySelector('.term-expression-list');          const reasonsContainer = node.querySelector('.term-reasons');          const pitchesContainer = node.querySelector('.term-pitch-accent-group-list'); -        const frequenciesContainer = node.querySelector('.frequencies'); +        const frequencyGroupListContainer = node.querySelector('.frequency-group-list');          const definitionsContainer = node.querySelector('.term-definition-list'); -        const bodyContainer = node.querySelector('.term-entry-body');          const {expressions, type, reasons, frequencies} = details;          const definitions = (type === 'term' ? [details] : details.definitions);          const merged = (type === 'termMerged' || type === 'termMergedByGlossary');          const pitches = DictionaryDataUtil.getPitchAccentInfos(details);          const pitchCount = pitches.reduce((i, v) => i + v.pitches.length, 0); +        const groupedFrequencies = DictionaryDataUtil.groupTermFrequencies(frequencies);          const uniqueExpressions = new Set();          const uniqueReadings = new Set(); @@ -72,15 +72,12 @@ class DisplayGenerator {          node.dataset.pitchAccentCount = `${pitchCount}`;          node.dataset.uniqueExpressionCount = `${uniqueExpressions.size}`;          node.dataset.uniqueReadingCount = `${uniqueReadings.size}`; - -        bodyContainer.dataset.sectionCount = `${ -            (definitions.length > 0 ? 1 : 0) + -            (pitches.length > 0 ? 1 : 0) -        }`; +        node.dataset.frequencyCount = `${frequencies.length}`; +        node.dataset.groupedFrequencyCount = `${groupedFrequencies.length}`;          this._appendMultiple(expressionsContainer, this._createTermExpression.bind(this), expressions);          this._appendMultiple(reasonsContainer, this._createTermReason.bind(this), reasons); -        this._appendMultiple(frequenciesContainer, this._createTermFrequencyTag.bind(this), frequencies); +        this._appendMultiple(frequencyGroupListContainer, this._createFrequencyGroup.bind(this), groupedFrequencies, false);          this._appendMultiple(pitchesContainer, this._createPitches.bind(this), pitches);          this._appendMultiple(definitionsContainer, this._createTermDefinitionItem.bind(this), definitions); @@ -91,7 +88,7 @@ class DisplayGenerator {          const node = this._templates.instantiate('kanji-entry');          const glyphContainer = node.querySelector('.kanji-glyph'); -        const frequenciesContainer = node.querySelector('.frequencies'); +        const frequencyGroupListContainer = node.querySelector('.frequency-group-list');          const tagContainer = node.querySelector('.tags');          const glossaryContainer = node.querySelector('.kanji-glossary-list');          const chineseReadingsContainer = node.querySelector('.kanji-readings-chinese'); @@ -102,8 +99,9 @@ class DisplayGenerator {          const dictionaryIndicesContainer = node.querySelector('.kanji-dictionary-indices');          glyphContainer.textContent = details.character; +        const groupedFrequencies = DictionaryDataUtil.groupKanjiFrequencies(details.frequencies); -        this._appendMultiple(frequenciesContainer, this._createKanjiFrequencyTag.bind(this), details.frequencies); +        this._appendMultiple(frequencyGroupListContainer, this._createFrequencyGroup.bind(this), groupedFrequencies, true);          this._appendMultiple(tagContainer, this._createTag.bind(this), details.tags);          this._appendMultiple(glossaryContainer, this._createKanjiGlossaryItem.bind(this), details.glossary);          this._appendMultiple(chineseReadingsContainer, this._createKanjiReading.bind(this), details.onyomi); @@ -128,7 +126,7 @@ class DisplayGenerator {      // Private      _createTermExpression(details) { -        const {termFrequency, furiganaSegments, expression, reading, termTags, frequencies} = details; +        const {termFrequency, furiganaSegments, expression, reading, termTags} = details;          const searchQueries = [];          if (expression) { searchQueries.push(expression); } @@ -138,7 +136,6 @@ class DisplayGenerator {          const expressionContainer = node.querySelector('.term-expression-text');          const tagContainer = node.querySelector('.tags'); -        const frequencyContainer = node.querySelector('.frequencies');          node.dataset.readingIsSame = `${!reading || reading === expression}`;          node.dataset.frequency = termFrequency; @@ -146,7 +143,6 @@ class DisplayGenerator {          this._appendFurigana(expressionContainer, furiganaSegments, this._appendKanjiLinks.bind(this));          this._appendMultiple(tagContainer, this._createTag.bind(this), termTags);          this._appendMultiple(tagContainer, this._createSearchTag.bind(this), searchQueries); -        this._appendMultiple(frequencyContainer, this._createTermFrequencyTag.bind(this), frequencies);          return node;      } @@ -467,36 +463,54 @@ class DisplayGenerator {          path.setAttribute('d', `M${pathPoints.join(' L')}`);      } -    _createTermFrequencyTag(details) { -        const {expression, reading, dictionary, frequency} = details; -        const node = this._templates.instantiate('term-tag-frequency'); +    _createFrequencyGroup(details, kanji) { +        const {dictionary, frequencyData} = details; +        const node = this._templates.instantiate('frequency-group-item'); + +        const tagList = node.querySelector('.frequency-tag-list'); +        const tag = this._createTag({notes: '', name: dictionary, category: 'frequency'}); +        tagList.appendChild(tag); + +        const frequencyListContainer = node.querySelector('.frequency-list'); +        const createItem = (kanji ? this._createKanjiFrequency.bind(this) : this._createTermFrequency.bind(this)); +        this._appendMultiple(frequencyListContainer, createItem, frequencyData, dictionary); + +        node.dataset.count = `${frequencyData.length}`; + +        return node; +    } + +    _createTermFrequency(details, dictionary) { +        const {expression, reading, frequencies} = details; +        const node = this._templates.instantiate('term-frequency-item'); -        node.querySelector('.tag-frequency-disambiguation-expression').textContent = expression; -        node.querySelector('.tag-frequency-disambiguation-reading').textContent = reading; -        node.querySelector('.tag-frequency-dictionary-name').textContent = dictionary; -        node.querySelector('.tag-frequency-value').textContent = frequency; +        const frequency = frequencies.join(', '); + +        node.querySelector('.frequency-disambiguation-expression').textContent = expression; +        node.querySelector('.frequency-disambiguation-reading').textContent = (reading !== null ? reading : ''); +        node.querySelector('.frequency-value').textContent = frequency;          node.dataset.expression = expression;          node.dataset.reading = reading; +        node.dataset.hasReading = `${reading !== null}`;          node.dataset.readingIsSame = `${reading === expression}`;          node.dataset.dictionary = dictionary; -        node.dataset.frequency = frequency; -        node.dataset.details = `${dictionary}: ${frequency}`; +        node.dataset.frequency = `${frequency}`;          return node;      } -    _createKanjiFrequencyTag(details) { -        const {character, dictionary, frequency} = details; -        const node = this._templates.instantiate('kanji-tag-frequency'); +    _createKanjiFrequency(details, dictionary) { +        const {character, frequencies} = details; +        const node = this._templates.instantiate('kanji-frequency-item'); + +        const frequency = frequencies.join(', '); -        node.querySelector('.tag-frequency-dictionary-name').textContent = dictionary; -        node.querySelector('.tag-frequency-value').textContent = frequency; +        node.querySelector('.frequency-value').textContent = frequency;          node.dataset.character = character;          node.dataset.dictionary = dictionary; -        node.dataset.frequency = frequency; -        node.dataset.details = `${dictionary}: ${frequency}`; +        node.dataset.frequency = `${frequency}`;          return node;      } |