123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211 |
- import * as DomUtil from '../common/dom_util.js';
- import { SemanticRole, SemanticType } from '../semantic_tree/semantic_meaning.js';
- import { SemanticNode } from '../semantic_tree/semantic_node.js';
- import { MMLTAGS } from '../semantic_tree/semantic_util.js';
- import { AbstractEnrichCase } from './abstract_enrich_case.js';
- import { CaseDoubleScript } from './case_double_script.js';
- import { CaseMultiscripts } from './case_multiscripts.js';
- import { CaseTensor } from './case_tensor.js';
- import * as EnrichMathml from './enrich_mathml.js';
- import { addMrow, setAttributes, Attribute } from './enrich_attr.js';
- export class CaseEmbellished extends AbstractEnrichCase {
- static test(semantic) {
- return !!(semantic.mathmlTree &&
- semantic.fencePointer &&
- !semantic.mathmlTree.getAttribute('data-semantic-type'));
- }
- static makeEmptyNode_(id) {
- const mrow = addMrow();
- const empty = new SemanticNode(id);
- empty.type = SemanticType.EMPTY;
- empty.mathmlTree = mrow;
- return empty;
- }
- static fencedMap_(fence, ids) {
- ids[fence.id] = fence.mathmlTree;
- if (!fence.embellished) {
- return;
- }
- CaseEmbellished.fencedMap_(fence.childNodes[0], ids);
- }
- constructor(semantic) {
- super(semantic);
- this.fenced = null;
- this.fencedMml = null;
- this.fencedMmlNodes = [];
- this.ofence = null;
- this.ofenceMml = null;
- this.ofenceMap = {};
- this.cfence = null;
- this.cfenceMml = null;
- this.cfenceMap = {};
- this.parentCleanup = [];
- }
- getMathml() {
- this.getFenced_();
- this.fencedMml = EnrichMathml.walkTree(this.fenced);
- this.getFencesMml_();
- if (this.fenced.type === SemanticType.EMPTY && !this.fencedMml.parentNode) {
- this.fencedMml.setAttribute(Attribute.ADDED, 'true');
- this.cfenceMml.parentNode.insertBefore(this.fencedMml, this.cfenceMml);
- }
- this.getFencedMml_();
- const rewrite = this.rewrite_();
- return rewrite;
- }
- fencedElement(node) {
- return (node.type === SemanticType.FENCED ||
- node.type === SemanticType.MATRIX ||
- node.type === SemanticType.VECTOR);
- }
- getFenced_() {
- let currentNode = this.semantic;
- while (!this.fencedElement(currentNode)) {
- currentNode = currentNode.childNodes[0];
- }
- this.fenced = currentNode.childNodes[0];
- this.ofence = currentNode.contentNodes[0];
- this.cfence = currentNode.contentNodes[1];
- CaseEmbellished.fencedMap_(this.ofence, this.ofenceMap);
- CaseEmbellished.fencedMap_(this.cfence, this.cfenceMap);
- }
- getFencedMml_() {
- let sibling = this.ofenceMml.nextSibling;
- sibling = sibling === this.fencedMml ? sibling : this.fencedMml;
- while (sibling && sibling !== this.cfenceMml) {
- this.fencedMmlNodes.push(sibling);
- sibling = sibling.nextSibling;
- }
- }
- getFencesMml_() {
- let currentNode = this.semantic;
- const ofenceIds = Object.keys(this.ofenceMap);
- const cfenceIds = Object.keys(this.cfenceMap);
- while ((!this.ofenceMml || !this.cfenceMml) &&
- currentNode !== this.fenced) {
- if (ofenceIds.indexOf(currentNode.fencePointer) !== -1 &&
- !this.ofenceMml) {
- this.ofenceMml = currentNode.mathmlTree;
- }
- if (cfenceIds.indexOf(currentNode.fencePointer) !== -1 &&
- !this.cfenceMml) {
- this.cfenceMml = currentNode.mathmlTree;
- }
- currentNode = currentNode.childNodes[0];
- }
- if (!this.ofenceMml) {
- this.ofenceMml = this.ofence.mathmlTree;
- }
- if (!this.cfenceMml) {
- this.cfenceMml = this.cfence.mathmlTree;
- }
- if (this.ofenceMml) {
- this.ofenceMml = EnrichMathml.ascendNewNode(this.ofenceMml);
- }
- if (this.cfenceMml) {
- this.cfenceMml = EnrichMathml.ascendNewNode(this.cfenceMml);
- }
- }
- rewrite_() {
- let currentNode = this.semantic;
- let result = null;
- const newNode = this.introduceNewLayer_();
- setAttributes(newNode, this.fenced.parent);
- while (!this.fencedElement(currentNode)) {
- const mml = currentNode.mathmlTree;
- const specialCase = this.specialCase_(currentNode, mml);
- if (specialCase) {
- currentNode = specialCase;
- }
- else {
- setAttributes(mml, currentNode);
- const mmlChildren = [];
- for (let i = 1, child; (child = currentNode.childNodes[i]); i++) {
- mmlChildren.push(EnrichMathml.walkTree(child));
- }
- currentNode = currentNode.childNodes[0];
- }
- const dummy = DomUtil.createElement('dummy');
- const saveChild = mml.childNodes[0];
- DomUtil.replaceNode(mml, dummy);
- DomUtil.replaceNode(newNode, mml);
- DomUtil.replaceNode(mml.childNodes[0], newNode);
- DomUtil.replaceNode(dummy, saveChild);
- if (!result) {
- result = mml;
- }
- }
- EnrichMathml.walkTree(this.ofence);
- EnrichMathml.walkTree(this.cfence);
- this.cleanupParents_();
- return result || newNode;
- }
- specialCase_(semantic, mml) {
- const mmlTag = DomUtil.tagName(mml);
- let parent = null;
- let caller;
- if (mmlTag === MMLTAGS.MSUBSUP) {
- parent = semantic.childNodes[0];
- caller = CaseDoubleScript;
- }
- else if (mmlTag === MMLTAGS.MMULTISCRIPTS) {
- if (semantic.type === SemanticType.SUPERSCRIPT ||
- semantic.type === SemanticType.SUBSCRIPT) {
- caller = CaseMultiscripts;
- }
- else if (semantic.type === SemanticType.TENSOR) {
- caller = CaseTensor;
- }
- if (caller &&
- semantic.childNodes[0] &&
- semantic.childNodes[0].role === SemanticRole.SUBSUP) {
- parent = semantic.childNodes[0];
- }
- else {
- parent = semantic;
- }
- }
- if (!parent) {
- return null;
- }
- const base = parent.childNodes[0];
- const empty = CaseEmbellished.makeEmptyNode_(base.id);
- parent.childNodes[0] = empty;
- mml = new caller(semantic).getMathml();
- parent.childNodes[0] = base;
- this.parentCleanup.push(mml);
- return parent.childNodes[0];
- }
- introduceNewLayer_() {
- const fullOfence = this.fullFence(this.ofenceMml);
- const fullCfence = this.fullFence(this.cfenceMml);
- let newNode = addMrow();
- DomUtil.replaceNode(this.fencedMml, newNode);
- this.fencedMmlNodes.forEach((node) => newNode.appendChild(node));
- newNode.insertBefore(fullOfence, this.fencedMml);
- newNode.appendChild(fullCfence);
- if (!newNode.parentNode) {
- const mrow = addMrow();
- while (newNode.childNodes.length > 0) {
- mrow.appendChild(newNode.childNodes[0]);
- }
- newNode.appendChild(mrow);
- newNode = mrow;
- }
- return newNode;
- }
- fullFence(fence) {
- const parent = this.fencedMml.parentNode;
- let currentFence = fence;
- while (currentFence.parentNode && currentFence.parentNode !== parent) {
- currentFence = currentFence.parentNode;
- }
- return currentFence;
- }
- cleanupParents_() {
- this.parentCleanup.forEach(function (x) {
- const parent = x.childNodes[1].getAttribute(Attribute.PARENT);
- x.childNodes[0].setAttribute(Attribute.PARENT, parent);
- });
- }
- }
|