mathml_store_util.js revision cedac228d2dd51db4b79ea1e72c7f249408ee061
1// Copyright 2014 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5/**
6 * @fileoverview Utility functions for mathml and mathjax rule store.
7 */
8
9goog.provide('cvox.MathmlStoreUtil');
10
11goog.require('cvox.MathUtil');
12goog.require('cvox.TraverseMath');
13
14
15/**
16 * Retrieves MathML sub element with same id as MathJax node.
17 * @param {!Node} inner A node internal to a MathJax node.
18 * @return {Node} The internal MathML node corresponding to the MathJax node.
19 */
20cvox.MathmlStoreUtil.matchMathjaxToMathml = function(inner) {
21  var mml = cvox.TraverseMath.getInstance().activeMathmlHost;
22  return mml.querySelector('#' + inner.id);
23};
24
25
26/**
27 * Retrieve an extender symbol for a given node.
28 * @param {!Node} jax The MathJax node.
29 * @return {Array.<Node>} The resulting node list.
30 */
31cvox.MathmlStoreUtil.retrieveMathjaxExtender = function(jax) {
32  var ext = cvox.MathmlStoreUtil.matchMathjaxToMathml(jax);
33  if (ext) {
34    return [ext];
35  }
36  return [];
37};
38
39
40/**
41 * Retrieve an extender symbol for a given node.
42 * @param {!Node} jax The MathJax node.
43 * @return {Array.<Node>} The resulting node list.
44 */
45cvox.MathmlStoreUtil.retrieveMathjaxLeaf = function(jax) {
46  var leaf = cvox.MathmlStoreUtil.matchMathjaxToMathml(jax);
47  if (leaf) {
48    return [leaf];
49  }
50  return [];
51};
52
53
54/**
55 * For a given MathJax node it returns the equivalent MathML node,
56 * if it is of the right tag.
57 * @param {!Node} jax The Mathjax node.
58 * @param {!string} tag The required tag.
59 * @return {Array.<Node>} The resulting node list.
60 */
61cvox.MathmlStoreUtil.checkMathjaxTag = function(jax, tag) {
62  var node = cvox.MathmlStoreUtil.matchMathjaxToMathml(jax);
63  if (node && node.tagName.toUpperCase() == tag) {
64    return [node];
65  }
66  return [];
67};
68
69
70/**
71 * Returns MathML node if MathJax is munder.
72 * @param {!Node} jax The Mathjax node.
73 * @return {Array.<Node>} The resulting node list.
74 */
75cvox.MathmlStoreUtil.checkMathjaxMunder = function(jax) {
76  return cvox.MathmlStoreUtil.checkMathjaxTag(jax, 'MUNDER');
77};
78
79
80/**
81 * Returns MathML node if MathJax is mover.
82 * @param {!Node} jax The Mathjax node.
83 * @return {Array.<Node>} The resulting node list.
84 */
85cvox.MathmlStoreUtil.checkMathjaxMover = function(jax) {
86  return cvox.MathmlStoreUtil.checkMathjaxTag(jax, 'MOVER');
87};
88
89
90/**
91 * Returns MathML node if MathJax is msub.
92 * @param {!Node} jax The Mathjax node.
93 * @return {Array.<Node>} The resulting node list.
94 */
95cvox.MathmlStoreUtil.checkMathjaxMsub = function(jax) {
96  return cvox.MathmlStoreUtil.checkMathjaxTag(jax, 'MSUB');
97};
98
99
100/**
101 * Returns MathML node if MathJax is msup.
102 * @param {!Node} jax The Mathjax node.
103 * @return {Array.<Node>} The resulting node list.
104 */
105cvox.MathmlStoreUtil.checkMathjaxMsup = function(jax) {
106  return cvox.MathmlStoreUtil.checkMathjaxTag(jax, 'MSUP');
107};
108
109
110/**
111 * Constructs a closure that returns separators for an MathML mfenced
112 * expression.
113 * Separators in MathML are represented by a list and used up one by one
114 * until the final element is used as the default.
115 * Example: a b c d e  and separators [+,-,*]
116 * would result in a + b - c * d * e.
117 * @param {string} separators String representing a list of mfenced separators.
118 * @return {function(): string|null} A closure that returns the next separator
119 * for an mfenced expression starting with the first node in nodes.
120 */
121cvox.MathmlStoreUtil.nextSeparatorFunction = function(separators) {
122  if (separators) {
123    // Mathjax does not expand empty separators.
124    if (separators.match(/^\s+$/)) {
125      return null;
126    } else {
127      var sepList = separators.replace(/\s/g, '')
128          .split('')
129              .filter(function(x) {return x;});
130    }
131  } else {
132    // When no separator is given MathML uses comma as default.
133    var sepList = [','];
134  }
135
136  return function() {
137    if (sepList.length > 1) {
138      return sepList.shift();
139    }
140    return sepList[0];
141  };
142};
143
144
145/**
146 * Computes the correct separators for each node.
147 * @param {Array.<Node>} nodes A node array.
148 * @param {string} context A context string.
149 * @return {function(): string} A closure that returns the next separator for an
150 * mfenced expression starting with the first node in nodes.
151 */
152cvox.MathmlStoreUtil.mfencedSeparators = function(nodes, context) {
153  var nextSeparator = cvox.MathmlStoreUtil.nextSeparatorFunction(context);
154  return function() {
155    return nextSeparator ? nextSeparator() : '';
156  };
157};
158
159
160/**
161 * Iterates over the list of content nodes of the parent of the given nodes.
162 * @param {Array.<Node>} nodes A node array.
163 * @param {string} context A context string.
164 * @return {function(): string} A closure that returns the content of the next
165 *     content node. Returns only context string if list is exhausted.
166 */
167cvox.MathmlStoreUtil.contentIterator = function(nodes, context) {
168  if (nodes.length > 0) {
169    var contentNodes = cvox.XpathUtil.evalXPath('../../content/*', nodes[0]);
170  } else {
171    var contentNodes = [];
172  }
173  return function() {
174    var content = contentNodes.shift();
175    return context + (content ? content.textContent : '');
176  };
177};
178