/************************************************************* * * Copyright (c) 2018 The MathJax Consortium * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ /** * @fileoverview Implements the CHTMLmmultiscripts wrapper for the MmlMmultiscripts object * * @author dpvc@mathjax.org (Davide Cervone) */ import {CHTMLWrapper, Constructor} from '../Wrapper.js'; import {CHTMLmsubsup} from './msubsup.js'; import {CommonMmultiscripts, CommonMmultiscriptsMixin} from '../../common/Wrappers/mmultiscripts.js'; import {MmlMmultiscripts} from '../../../core/MmlTree/MmlNodes/mmultiscripts.js'; import {BBox} from '../BBox.js'; import {StyleList} from '../../common/CssStyles.js'; /*****************************************************************/ /** * The CHTMLmmultiscripts wrapper for the MmlMmultiscripts object * * @template N The HTMLElement node class * @template T The Text node class * @template D The Document class */ export class CHTMLmmultiscripts extends CommonMmultiscriptsMixin, Constructor>>(CHTMLmsubsup) { public static kind = MmlMmultiscripts.prototype.kind; public static styles: StyleList = { 'mjx-prescripts': { display: 'inline-table', 'padding-left': '.05em' // scriptspace }, 'mjx-scripts': { display: 'inline-table', 'padding-right': '.05em' // scriptspace }, 'mjx-prescripts > mjx-row > mjx-cell': { 'text-align': 'right' } }; /*************************************************************/ /** * @override */ public toCHTML(parent: N) { const chtml = this.standardCHTMLnode(parent); const data = this.getScriptData(); // // Combine the bounding boxes of the pre- and post-scripts, // and get the resulting baseline offsets // const sub = this.combinePrePost(data.sub, data.psub); const sup = this.combinePrePost(data.sup, data.psup); const [u, v, q] = this.getUVQ(data.base, sub, sup); // // Place the pre-scripts, then the base, then the post-scripts // if (data.numPrescripts) { this.addScripts(u, -v, true, data.psub, data.psup, this.firstPrescript, data.numPrescripts); } this.childNodes[0].toCHTML(chtml); if (data.numScripts) { this.addScripts(u, -v, false, data.sub, data.sup, 1, data.numScripts); } } /** * Create a table with the super and subscripts properly separated and aligned. * * @param {number} u The baseline offset for the superscripts * @param {number} v The baseline offset for the subscripts * @param {boolean} isPre True for prescripts, false for scripts * @param {BBox} sub The subscript bounding box * @param {BBox} sup The superscript bounding box * @param {number} i The starting index for the scripts * @param {number} n The number of sub/super-scripts */ protected addScripts(u: number, v: number, isPre: boolean, sub: BBox, sup: BBox, i: number, n: number) { const adaptor = this.adaptor; const q = (u - sup.d) + (v - sub.h); // separation of scripts const U = (u < 0 && v === 0 ? sub.h + u : u); // vertical offset of table const rowdef = (q > 0 ? {style: {height: this.em(q)}} : {}); const tabledef = (U ? {style: {'vertical-align': this.em(U)}} : {}); const supRow = this.html('mjx-row'); const sepRow = this.html('mjx-row', rowdef); const subRow = this.html('mjx-row'); const name = 'mjx-' + (isPre ? 'pre' : '') + 'scripts'; adaptor.append(this.chtml, this.html(name, tabledef, [supRow, sepRow, subRow])); let m = i + 2 * n; while (i < m) { this.childNodes[i++].toCHTML(adaptor.append(subRow, this.html('mjx-cell')) as N); this.childNodes[i++].toCHTML(adaptor.append(supRow, this.html('mjx-cell')) as N); } } }