diff options
Diffstat (limited to 'ext/js/display/sandbox')
| -rw-r--r-- | ext/js/display/sandbox/pronunciation-generator.js | 56 | ||||
| -rw-r--r-- | ext/js/display/sandbox/structured-content-generator.js | 101 | 
2 files changed, 143 insertions, 14 deletions
| diff --git a/ext/js/display/sandbox/pronunciation-generator.js b/ext/js/display/sandbox/pronunciation-generator.js index 76d5e2b1..d113485f 100644 --- a/ext/js/display/sandbox/pronunciation-generator.js +++ b/ext/js/display/sandbox/pronunciation-generator.js @@ -17,10 +17,21 @@   */  export class PronunciationGenerator { +    /** +     * @param {import('../../language/sandbox/japanese-util.js').JapaneseUtil} japaneseUtil +     */      constructor(japaneseUtil) { +        /** @type {import('../../language/sandbox/japanese-util.js').JapaneseUtil} */          this._japaneseUtil = japaneseUtil;      } +    /** +     * @param {string[]} morae +     * @param {number} downstepPosition +     * @param {number[]} nasalPositions +     * @param {number[]} devoicePositions +     * @returns {HTMLSpanElement} +     */      createPronunciationText(morae, downstepPosition, nasalPositions, devoicePositions) {          const jp = this._japaneseUtil;          const nasalPositionsSet = nasalPositions.length > 0 ? new Set(nasalPositions) : null; @@ -63,7 +74,7 @@ export class PronunciationGenerator {                  group.className = 'pronunciation-character-group';                  const n2 = characterNodes[0]; -                const character = n2.textContent; +                const character = /** @type {string} */ (n2.textContent);                  const characterInfo = jp.getKanaDiacriticInfo(character);                  if (characterInfo !== null) { @@ -81,7 +92,7 @@ export class PronunciationGenerator {                  n3.className = 'pronunciation-nasal-indicator';                  group.appendChild(n3); -                n2.parentNode.replaceChild(group, n2); +                /** @type {ParentNode} */ (n2.parentNode).replaceChild(group, n2);                  group.insertBefore(n2, group.firstChild);              } @@ -94,6 +105,11 @@ export class PronunciationGenerator {          return container;      } +    /** +     * @param {string[]} morae +     * @param {number} downstepPosition +     * @returns {SVGSVGElement} +     */      createPronunciationGraph(morae, downstepPosition) {          const jp = this._japaneseUtil;          const ii = morae.length; @@ -145,12 +161,16 @@ export class PronunciationGenerator {          return svg;      } +    /** +     * @param {number} downstepPosition +     * @returns {HTMLSpanElement} +     */      createPronunciationDownstepPosition(downstepPosition) { -        downstepPosition = `${downstepPosition}`; +        const downstepPositionString = `${downstepPosition}`;          const n1 = document.createElement('span');          n1.className = 'pronunciation-downstep-notation'; -        n1.dataset.downstepPosition = downstepPosition; +        n1.dataset.downstepPosition = downstepPositionString;          let n2 = document.createElement('span');          n2.className = 'pronunciation-downstep-notation-prefix'; @@ -159,7 +179,7 @@ export class PronunciationGenerator {          n2 = document.createElement('span');          n2.className = 'pronunciation-downstep-notation-number'; -        n2.textContent = downstepPosition; +        n2.textContent = downstepPositionString;          n1.appendChild(n2);          n2 = document.createElement('span'); @@ -172,15 +192,33 @@ export class PronunciationGenerator {      // Private +    /** +     * @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'));      } +    /** +     * @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'));      } +    /** +     * @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'); @@ -189,6 +227,14 @@ export class PronunciationGenerator {          container.appendChild(node);      } +    /** +     * @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); diff --git a/ext/js/display/sandbox/structured-content-generator.js b/ext/js/display/sandbox/structured-content-generator.js index 227892d6..5a91b01c 100644 --- a/ext/js/display/sandbox/structured-content-generator.js +++ b/ext/js/display/sandbox/structured-content-generator.js @@ -17,28 +17,51 @@   */  export class StructuredContentGenerator { +    /** +     * @param {import('../../display/display-content-manager.js').DisplayContentManager|import('../../templates/sandbox/anki-template-renderer-content-manager.js').AnkiTemplateRendererContentManager} contentManager +     * @param {import('../../language/sandbox/japanese-util.js').JapaneseUtil} japaneseUtil +     * @param {Document} document +     */      constructor(contentManager, japaneseUtil, document) { +        /** @type {import('../../display/display-content-manager.js').DisplayContentManager|import('../../templates/sandbox/anki-template-renderer-content-manager.js').AnkiTemplateRendererContentManager} */          this._contentManager = contentManager; +        /** @type {import('../../language/sandbox/japanese-util.js').JapaneseUtil} */          this._japaneseUtil = japaneseUtil; +        /** @type {Document} */          this._document = document;      } +    /** +     * @param {HTMLElement} node +     * @param {import('structured-content').Content} content +     * @param {string} dictionary +     */      appendStructuredContent(node, content, dictionary) {          node.classList.add('structured-content');          this._appendStructuredContent(node, content, dictionary, null);      } +    /** +     * @param {import('structured-content').Content} content +     * @param {string} dictionary +     * @returns {HTMLElement} +     */      createStructuredContent(content, dictionary) {          const node = this._createElement('span', 'structured-content');          this._appendStructuredContent(node, content, dictionary, null);          return node;      } +    /** +     * @param {import('structured-content').ImageElementBase} data +     * @param {string} dictionary +     * @returns {HTMLAnchorElement} +     */      createDefinitionImage(data, dictionary) {          const {              path, -            width, -            height, +            width = 100, +            height = 100,              preferredWidth,              preferredHeight,              title, @@ -65,7 +88,7 @@ export class StructuredContentGenerator {              (hasPreferredHeight ? preferredHeight / invAspectRatio : width)          ); -        const node = this._createElement('a', 'gloss-image-link'); +        const node = /** @type {HTMLAnchorElement} */ (this._createElement('a', 'gloss-image-link'));          node.target = '_blank';          node.rel = 'noreferrer noopener'; @@ -78,7 +101,7 @@ export class StructuredContentGenerator {          const imageBackground = this._createElement('span', 'gloss-image-background');          imageContainer.appendChild(imageBackground); -        const image = this._createElement('img', 'gloss-image'); +        const image = /** @type {HTMLImageElement} */ (this._createElement('img', 'gloss-image'));          image.alt = '';          imageContainer.appendChild(image); @@ -126,6 +149,12 @@ export class StructuredContentGenerator {      // Private +    /** +     * @param {HTMLElement} container +     * @param {import('structured-content').Content|undefined} content +     * @param {string} dictionary +     * @param {?string} language +     */      _appendStructuredContent(container, content, dictionary, language) {          if (typeof content === 'string') {              if (content.length > 0) { @@ -151,16 +180,29 @@ export class StructuredContentGenerator {          }      } +    /** +     * @param {string} tagName +     * @param {string} className +     * @returns {HTMLElement} +     */      _createElement(tagName, className) {          const node = this._document.createElement(tagName);          node.className = className;          return node;      } +    /** +     * @param {string} data +     * @returns {Text} +     */      _createTextNode(data) {          return this._document.createTextNode(data);      } +    /** +     * @param {HTMLElement} element +     * @param {import('structured-content').Data} data +     */      _setElementDataset(element, data) {          for (let [key, value] of Object.entries(data)) {              if (key.length > 0) { @@ -175,6 +217,13 @@ export class StructuredContentGenerator {          }      } +    /** +     * @param {HTMLAnchorElement} node +     * @param {HTMLImageElement} image +     * @param {HTMLElement} imageBackground +     * @param {?string} url +     * @param {boolean} unloaded +     */      _setImageData(node, image, imageBackground, url, unloaded) {          if (url !== null) {              image.src = url; @@ -189,6 +238,12 @@ export class StructuredContentGenerator {          }      } +    /** +     * @param {import('structured-content').Element} content +     * @param {string} dictionary +     * @param {?string} language +     * @returns {?HTMLElement} +     */      _createStructuredContentGenericElement(content, dictionary, language) {          const {tag} = content;          switch (tag) { @@ -222,6 +277,13 @@ export class StructuredContentGenerator {          return null;      } +    /** +     * @param {string} tag +     * @param {import('structured-content').UnstyledElement} content +     * @param {string} dictionary +     * @param {?string} language +     * @returns {HTMLElement} +     */      _createStructuredContentTableElement(tag, content, dictionary, language) {          const container = this._createElement('div', 'gloss-sc-table-container');          const table = this._createStructuredContentElement(tag, content, dictionary, language, 'table', true, false); @@ -229,6 +291,16 @@ export class StructuredContentGenerator {          return container;      } +    /** +     * @param {string} tag +     * @param {import('structured-content').StyledElement|import('structured-content').UnstyledElement|import('structured-content').TableElement|import('structured-content').LineBreak} content +     * @param {string} dictionary +     * @param {?string} language +     * @param {'simple'|'table'|'table-cell'} type +     * @param {boolean} hasChildren +     * @param {boolean} hasStyle +     * @returns {HTMLElement} +     */      _createStructuredContentElement(tag, content, dictionary, language, type, hasChildren, hasStyle) {          const node = this._createElement(tag, `gloss-sc-${tag}`);          const {data, lang} = content; @@ -240,14 +312,15 @@ export class StructuredContentGenerator {          switch (type) {              case 'table-cell':                  { -                    const {colSpan, rowSpan} = content; -                    if (typeof colSpan === 'number') { node.colSpan = colSpan; } -                    if (typeof rowSpan === 'number') { node.rowSpan = rowSpan; } +                    const cell = /** @type {HTMLTableCellElement} */ (node); +                    const {colSpan, rowSpan} = /** @type {import('structured-content').TableElement} */ (content); +                    if (typeof colSpan === 'number') { cell.colSpan = colSpan; } +                    if (typeof rowSpan === 'number') { cell.rowSpan = rowSpan; }                  }                  break;          }          if (hasStyle) { -            const {style} = content; +            const {style} = /** @type {import('structured-content').StyledElement} */ (content);              if (typeof style === 'object' && style !== null) {                  this._setStructuredContentElementStyle(node, style);              } @@ -258,6 +331,10 @@ export class StructuredContentGenerator {          return node;      } +    /** +     * @param {HTMLElement} node +     * @param {import('structured-content').StructuredContentStyle} contentStyle +     */      _setStructuredContentElementStyle(node, contentStyle) {          const {style} = node;          const { @@ -290,6 +367,12 @@ export class StructuredContentGenerator {          if (typeof listStyleType === 'string') { style.listStyleType = listStyleType; }      } +    /** +     * @param {import('structured-content').LinkElement} content +     * @param {string} dictionary +     * @param {?string} language +     * @returns {HTMLAnchorElement} +     */      _createLinkElement(content, dictionary, language) {          let {href} = content;          const internal = href.startsWith('?'); @@ -297,7 +380,7 @@ export class StructuredContentGenerator {              href = `${location.protocol}//${location.host}/search.html${href.length > 1 ? href : ''}`;          } -        const node = this._createElement('a', 'gloss-link'); +        const node = /** @type {HTMLAnchorElement} */ (this._createElement('a', 'gloss-link'));          node.dataset.external = `${!internal}`;          const text = this._createElement('span', 'gloss-link-text'); |