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 Speech rules for mathml and mathjax nodes. 7 */ 8 9goog.provide('cvox.MathmlStoreRules'); 10 11goog.require('cvox.MathStore'); 12goog.require('cvox.MathmlStore'); 13goog.require('cvox.MathmlStoreUtil'); 14goog.require('cvox.StoreUtil'); 15 16 17/** 18 * Rule initialization. 19 * @constructor 20 */ 21cvox.MathmlStoreRules = function() { 22 // Custom functions used in the rules. 23 cvox.MathmlStoreRules.initCustomFunctions_(); 24 cvox.MathmlStoreRules.initDefaultRules_(); // MathML rules. 25 cvox.MathmlStoreRules.initMathjaxRules_(); // MathJax Rules 26 cvox.MathmlStoreRules.initAliases_(); // MathJax Aliases for MathML rules. 27 cvox.MathmlStoreRules.initSpecializationRules_(); // Square, cube, etc. 28 cvox.MathmlStoreRules.initSemanticRules_(); 29}; 30goog.addSingletonGetter(cvox.MathmlStoreRules); 31 32 33/** 34 * @type {cvox.MathStore} 35 */ 36cvox.MathmlStoreRules.mathStore = cvox.MathmlStore.getInstance(); 37/** 38 * @override 39 */ 40cvox.MathmlStoreRules.mathStore.initialize = cvox.MathmlStoreRules.getInstance; 41 42// These are used to work around Closure's rules for aliasing. 43/** @private */ 44cvox.MathmlStoreRules.defineDefaultMathmlRule_ = goog.bind( 45 cvox.MathmlStoreRules.mathStore.defineDefaultMathmlRule, 46 cvox.MathmlStoreRules.mathStore); 47/** @private */ 48cvox.MathmlStoreRules.defineRule_ = goog.bind( 49 cvox.MathmlStoreRules.mathStore.defineRule, 50 cvox.MathmlStoreRules.mathStore); 51/** @private */ 52cvox.MathmlStoreRules.defineRuleAlias_ = goog.bind( 53 cvox.MathmlStoreRules.mathStore.defineRuleAlias, 54 cvox.MathmlStoreRules.mathStore); 55/** @private */ 56cvox.MathmlStoreRules.addContextFunction_ = goog.bind( 57 cvox.MathmlStoreRules.mathStore.contextFunctions.add, 58 cvox.MathmlStoreRules.mathStore.contextFunctions); 59/** @private */ 60cvox.MathmlStoreRules.addCustomQuery_ = goog.bind( 61 cvox.MathmlStoreRules.mathStore.customQueries.add, 62 cvox.MathmlStoreRules.mathStore.customQueries); 63 64goog.scope(function() { 65var defineDefaultMathmlRule = cvox.MathmlStoreRules.defineDefaultMathmlRule_; 66var defineRule = cvox.MathmlStoreRules.defineRule_; 67var defineRuleAlias = cvox.MathmlStoreRules.defineRuleAlias_; 68 69var addCTXF = cvox.MathmlStoreRules.addContextFunction_; 70var addCQF = cvox.MathmlStoreRules.addCustomQuery_; 71 72/** 73 * Initialize the custom functions. 74 * @private 75 */ 76cvox.MathmlStoreRules.initCustomFunctions_ = function() { 77 addCTXF('CTXFnodeCounter', cvox.StoreUtil.nodeCounter); 78 addCTXF('CTXFmfSeparators', cvox.MathmlStoreUtil.mfencedSeparators); 79 addCTXF('CTXFcontentIterator', cvox.MathmlStoreUtil.contentIterator); 80 81 addCQF('CQFextender', cvox.MathmlStoreUtil.retrieveMathjaxExtender); 82 addCQF('CQFmathmlmunder', cvox.MathmlStoreUtil.checkMathjaxMunder); 83 addCQF('CQFmathmlmover', cvox.MathmlStoreUtil.checkMathjaxMover); 84 addCQF('CQFmathmlmsub', cvox.MathmlStoreUtil.checkMathjaxMsub); 85 addCQF('CQFmathmlmsup', cvox.MathmlStoreUtil.checkMathjaxMsup); 86 addCQF('CQFlookupleaf', cvox.MathmlStoreUtil.retrieveMathjaxLeaf); 87 88}; 89 90 91/** 92 * Initialize the default mathrules. 93 * @private 94 */ 95cvox.MathmlStoreRules.initDefaultRules_ = function() { 96 // Initial rule 97 defineDefaultMathmlRule('math', '[m] ./*'); 98 99 // Space elements 100 defineDefaultMathmlRule('mspace', '[p] (pause:250)'); 101 defineDefaultMathmlRule('mstyle', '[m] ./*'); 102 defineDefaultMathmlRule('mpadded', '[m] ./*'); 103 defineDefaultMathmlRule('merror', '[m] ./*'); 104 defineDefaultMathmlRule('mphantom', '[m] ./*'); 105 106 // Token elements. 107 defineDefaultMathmlRule('mtext', '[t] text(); [p] (pause:200)'); 108 defineDefaultMathmlRule('mi', '[n] text()'); 109 defineDefaultMathmlRule('mo', '[n] text() (rate:-0.1)'); 110 defineDefaultMathmlRule('mn', '[n] text()'); 111 112 // Dealing with fonts. 113 defineRule('mtext-variant', 'default.default', 114 '[t] "begin"; [t] @mathvariant (pause:150);' + 115 '[t] text() (pause:150); [t] "end"; ' + 116 '[t] @mathvariant (pause:200)', 117 'self::mathml:mtext', '@mathvariant', '@mathvariant!="normal"'); 118 119 defineRule('mi-variant', 'default.default', 120 '[t] @mathvariant; [n] text()', 121 'self::mathml:mi', '@mathvariant', '@mathvariant!="normal"'); 122 123 defineRuleAlias('mi-variant', 'self::mathml:mn', // mn 124 '@mathvariant', '@mathvariant!="normal"'); 125 126 defineRule('mo-variant', 'default.default', 127 '[t] @mathvariant; [n] text() (rate:-0.1)', 128 'self::mathml:mo', '@mathvariant', '@mathvariant!="normal"'); 129 130 defineDefaultMathmlRule( 131 'ms', 132 '[t] "string" (pitch:0.5, rate:0.5); [t] text()'); 133 134 // Script elements. 135 defineDefaultMathmlRule( 136 'msup', '[n] ./*[1]; [t] "super";' + 137 '[n] ./*[2] (pitch:0.35); [p] (pause:300)'); 138 defineDefaultMathmlRule( 139 'msubsup', 140 '[n] ./*[1]; [t] "sub"; [n] ./*[2] (pitch:-0.35); [p] (pause:200);' + 141 '[t] "super"; [n] ./*[3] (pitch:0.35); [p] (pause:300)' 142 ); 143 defineDefaultMathmlRule( 144 'msub', 145 '[n] ./*[1]; [t] "sub"; [n] ./*[2] (pitch:-0.35); [p] (pause:300)'); 146 defineDefaultMathmlRule( 147 'mover', '[n] ./*[2] (pitch:0.35); [p] (pause:200);' + 148 ' [t] "over"; [n] ./*[1]; [p] (pause:400)'); 149 defineDefaultMathmlRule( 150 'munder', 151 '[n] ./*[2] (pitch:-0.35); [t] "under"; [n] ./*[1]; [p] (pause:400)'); 152 defineDefaultMathmlRule( 153 'munderover', 154 '[n] ./*[2] (pitch:-0.35); [t] "under and"; [n] ./*[3] (pitch:0.35);' + 155 ' [t] "over"; [n] ./*[1]; [p] (pause:400)'); 156 157 // Layout elements. 158 defineDefaultMathmlRule('mrow', '[m] ./*'); 159 defineDefaultMathmlRule( 160 'msqrt', '[t] "Square root of"; [m] ./* (rate:0.2); [p] (pause:400)'); 161 defineDefaultMathmlRule( 162 'mroot', '[t] "root of order"; [n] ./*[2]; [t] "of";' + 163 '[n] ./*[1] (rate:0.2); [p] (pause:400)'); 164 defineDefaultMathmlRule( 165 'mfrac', ' [p] (pause:400); [n] ./*[1] (pitch:0.3);' + 166 ' [t] "divided by"; [n] ./*[2] (pitch:-0.3); [p] (pause:400)'); 167 168 169 defineRule( 170 'mfenced-single', 'default.default', 171 '[t] @open (context:"opening"); [m] ./* (separator:@separators);' + 172 '[t] @close (context:"closing")', 173 'self::mathml:mfenced', 'string-length(string(@separators))=1'); 174 175 defineRule( 176 'mfenced-empty', 'default.default', 177 '[t] @open (context:"opening"); [m] ./*;' + 178 '[t] @close (context:"closing")', 179 'self::mathml:mfenced', 'string-length(string(@separators))=1', 180 'string(@separators)=" "'); 181 182 defineRule( 183 'mfenced-comma', 'default.default', 184 '[t] @open (context:"opening"); [m] ./* (separator:"comma");' + 185 '[t] @close (context:"closing")', 186 'self::mathml:mfenced'); 187 188 defineRule( 189 'mfenced-multi', 'default.default', 190 '[t] @open (context:"opening"); [m] ./* (sepFunc:CTXFmfSeparators,' + 191 'separator:@separators); [t] @close (context:"closing")', 192 'self::mathml:mfenced', 'string-length(string(@separators))>1'); 193 194 // Mtable rules. 195 defineRule( 196 'mtable', 'default.default', 197 '[t] "matrix"; [m] ./* (ctxtFunc:CTXFnodeCounter,' + 198 'context:"row",pause:100)', 199 'self::mathml:mtable'); 200 201 defineRule( 202 'mtr', 'default.default', 203 '[m] ./* (ctxtFunc:CTXFnodeCounter,context:"column",pause:100)', 204 'self::mathml:mtr'); 205 206 defineRule( 207 'mtd', 'default.default', 208 '[m] ./*', 'self::mathml:mtd'); 209 210 // Mtable superbrief rules. 211 defineRule( 212 'mtable', 'default.superbrief', 213 '[t] count(child::mathml:mtr); [t] "by";' + 214 '[t] count(child::mathml:mtr[1]/mathml:mtd); [t] "matrix";', 215 'self::mathml:mtable'); 216 217 // Mtable short rules. 218 defineRule( 219 'mtable', 'default.short', 220 '[t] "matrix"; [m] ./*', 221 'self::mathml:mtable'); 222 223 defineRule( 224 'mtr', 'default.short', 225 '[m] ./*', 'self::mathml:mtr'); 226 227 defineRule( 228 'mtd', 'default.short', 229 '[t] "Element"; [t] count(./preceding-sibling::mathml:mtd)+1;' + 230 '[t] count(./parent::mathml:mtr/preceding-sibling::mathml:mtr)+1;' + 231 '[p] (pause:500); [m] ./*', 232 'self::mathml:mtd'); 233 234 // Mmultiscripts rules. 235 defineRule( 236 'mmultiscripts-4', 'default.default', 237 '[n] ./*[1]; [p] (pause:200);' + 238 '[t] "left sub"; [n] ./*[5] (pitch:-0.35); [p] (pause:200);' + 239 '[t] "left super"; [n] ./*[6] (pitch:0.35); [p] (pause:200);' + 240 '[t] "right sub"; [n] ./*[2] (pitch:-0.35); [p] (pause:200);' + 241 '[t] "right super"; [n] ./*[3] (pitch:0.35); [p] (pause:300);', 242 'self::mathml:mmultiscripts'); 243 defineRule( 244 'mmultiscripts-3-1', 'default.default', 245 '[n] ./*[1]; [p] (pause:200);' + 246 '[t] "left sub"; [n] ./*[5] (pitch:-0.35); [p] (pause:200);' + 247 '[t] "left super"; [n] ./*[6] (pitch:0.35); [p] (pause:200);' + 248 '[t] "right super"; [n] ./*[3] (pitch:0.35); [p] (pause:300);', 249 'self::mathml:mmultiscripts', './mathml:none=./*[2]', 250 './mathml:mprescripts=./*[4]'); 251 defineRule( 252 'mmultiscripts-3-2', 'default.default', 253 '[n] ./*[1]; [p] (pause:200);' + 254 '[t] "left sub"; [n] ./*[5] (pitch:-0.35); [p] (pause:200);' + 255 '[t] "left super"; [n] ./*[6] (pitch:0.35); [p] (pause:200);' + 256 '[t] "right sub"; [n] ./*[2] (pitch:-0.35); [p] (pause:200);', 257 'self::mathml:mmultiscripts', './mathml:none=./*[3]', 258 './mathml:mprescripts=./*[4]'); 259 defineRule( 260 'mmultiscripts-3-3', 'default.default', 261 '[n] ./*[1]; [p] (pause:200);' + 262 '[t] "left super"; [n] ./*[6] (pitch:0.35); [p] (pause:200);' + 263 '[t] "right sub"; [n] ./*[2] (pitch:-0.35); [p] (pause:200);' + 264 '[t] "right super"; [n] ./*[3] (pitch:0.35); [p] (pause:300);', 265 'self::mathml:mmultiscripts', './mathml:none=./*[5]', 266 './mathml:mprescripts=./*[4]'); 267 defineRule( 268 'mmultiscripts-3-4', 'default.default', 269 '[n] ./*[1]; [p] (pause:200);' + 270 '[t] "left sub"; [n] ./*[5] (pitch:-0.35); [p] (pause:200);' + 271 '[t] "right sub"; [n] ./*[2] (pitch:-0.35); [p] (pause:200);' + 272 '[t] "right super"; [n] ./*[3] (pitch:0.35); [p] (pause:300);', 273 'self::mathml:mmultiscripts', './mathml:none=./*[6]', 274 './mathml:mprescripts=./*[4]'); 275 defineRule( 276 'mmultiscripts-2-1', 'default.default', 277 '[n] ./*[1]; [p] (pause:200);' + 278 '[t] "left sub"; [n] ./*[5] (pitch:-0.35); [p] (pause:200);' + 279 '[t] "left super"; [n] ./*[6] (pitch:0.35); [p] (pause:300);', 280 'self::mathml:mmultiscripts', './mathml:none=./*[2]', 281 './mathml:none=./*[3]', './mathml:mprescripts=./*[4]'); 282 defineRule( 283 'mmultiscripts-1-1', 'default.default', 284 '[n] ./*[1]; [p] (pause:200);' + 285 '[t] "left super"; [n] ./*[6] (pitch:0.35); [p] (pause:300);', 286 'self::mathml:mmultiscripts', './mathml:none=./*[2]', 287 './mathml:none=./*[3]', './mathml:mprescripts=./*[4]', 288 './mathml:none=./*[5]'); 289 defineRule( 290 'mmultiscripts-1-2', 'default.default', 291 '[n] ./*[1]; [p] (pause:200);' + 292 '[t] "left sub"; [n] ./*[5] (pitch:-0.35); [p] (pause:200);', 293 'self::mathml:mmultiscripts', './mathml:none=./*[2]', 294 './mathml:none=./*[3]', './mathml:mprescripts=./*[4]', 295 './mathml:none=./*[6]'); 296}; 297 298 299/** 300 * Initialize mathJax Rules 301 * @private 302 */ 303cvox.MathmlStoreRules.initMathjaxRules_ = function() { 304 // Initial rule 305 defineRule('mj-math', 'default.default', 306 '[n] ./*[1]/*[1]/*[1]', 'self::span[@class="math"]'); 307 308 // Token Elements 309 defineRule( 310 'mj-leaf', 'default.default', 311 '[n] CQFlookupleaf', 'self::span[@class="mi"]'); 312 defineRuleAlias('mj-leaf', 'self::span[@class="mo"]'); 313 defineRuleAlias('mj-leaf', 'self::span[@class="mn"]'); 314 defineRuleAlias('mj-leaf', 'self::span[@class="mtext"]'); 315 defineRule( 316 'mj-mo-ext', 'default.default', 317 '[n] CQFextender', 'self::span[@class="mo"]', 318 './*[1]/*[1]/text()', './*[1]/*[2]/text()'); 319 defineRule( 320 'mj-texatom', 'default.default', 321 '[n] ./*[1]', 'self::span[@class="texatom"]'); 322 323 // Script elements. 324 defineRule( 325 'mj-msubsup', 'default.default', 326 '[n] ./*[1]/*[1]/*[1]; [t] "sub"; [n] ./*[1]/*[3]/*[1] (pitch:-0.35);' + 327 '[p] (pause:200); [t] "super"; [n] ./*[1]/*[2]/*[1] (pitch:0.35);' + 328 '[p] (pause:300)', 329 'self::span[@class="msubsup"]'); 330 defineRule( 331 'mj-msub', 'default.default', 332 '[n] ./*[1]/*[1]/*[1]; [t] "sub";' + 333 '[n] ./*[1]/*[2]/*[1] (pitch:-0.35); [p] (pause:300)', 334 'self::span[@class="msub"]'); 335 defineRule( 336 'mj-msup', 'default.default', 337 '[n] ./*[1]/*[1]/*[1]; [t] "super";' + 338 '[n] ./*[1]/*[2]/*[1] (pitch:0.35); [p] (pause:300)', 339 'self::span[@class="msup"]'); 340 defineRule( 341 'mj-munderover', 'default.default', 342 '[n] ./*[1]/*[2]/*[1] (pitch:0.35); [t] "under and";' + 343 '[n] ./*[1]/*[3]/*[1] (pitch:-0.35); [t] "over";' + 344 '[n] ./*[1]/*[1]/*[1]; [p] (pause:400)', 345 'self::span[@class="munderover"]'); 346 defineRule( 347 'mj-munder', 'default.default', 348 '[n] ./*[1]/*[2]/*[1] (pitch:0.35); [t] "under";' + 349 '[n] ./*[1]/*[1]/*[1]; [p] (pause:400)', 350 'self::span[@class="munder"]'); 351 defineRule( 352 'mj-mover', 'default.default', 353 '[n] ./*[1]/*[2]/*[1] (pitch:0.35); [t] "over";' + 354 '[n] ./*[1]/*[1]/*[1]; [p] (pause:400)', 355 'self::span[@class="mover"]'); 356 357 358 // Layout elements. 359 defineRule( 360 'mj-mfrac', 'default.default', 361 '[p] (pause:250); [n] ./*[1]/*[1]/*[1] (pitch:0.3); [p] (pause:250);' + 362 ' [t] "divided by"; [n] ./*[1]/*[2]/*[1] (pitch:-0.3);' + 363 '[p] (pause:400)', 364 'self::span[@class="mfrac"]'); 365 defineRule( 366 'mj-msqrt', 'default.default', 367 '[t] "Square root of";' + 368 '[n] ./*[1]/*[1]/*[1] (rate:0.2); [p] (pause:400)', 369 'self::span[@class="msqrt"]'); 370 defineRule( 371 'mj-mroot', 'default.default', 372 '[t] "root of order"; [n] ./*[1]/*[4]/*[1]; [t] "of";' + 373 '[n] ./*[1]/*[1]/*[1] (rate:0.2); [p] (pause:400)', 374 'self::span[@class="mroot"]'); 375 376 defineRule( 377 'mj-mfenced', 'default.default', 378 '[t] "opening"; [n] ./*[1]; ' + 379 '[m] ./*[position()>1 and position()<last()];' + 380 ' [t] "closing"; [n] ./*[last()]', 381 'self::span[@class="mfenced"]'); 382 383 // Mtable short rules. 384 defineRuleAlias('mj-leaf', 'self::span[@class="mtable"]'); 385 // Mmultiscripts rules. 386 defineRuleAlias('mj-leaf', 'self::span[@class="mmultiscripts"]'); 387}; 388 389 390/** 391 * Initialize mathJax Aliases 392 * @private 393 */ 394cvox.MathmlStoreRules.initAliases_ = function() { 395 // Space elements 396 defineRuleAlias('mspace', 'self::span[@class="mspace"]'); 397 defineRuleAlias('mstyle', 'self::span[@class="mstyle"]'); 398 defineRuleAlias('mpadded', 'self::span[@class="mpadded"]'); 399 defineRuleAlias('merror', 'self::span[@class="merror"]'); 400 defineRuleAlias('mphantom', 'self::span[@class="mphantom"]'); 401 402 // Token elements. 403 defineRuleAlias('ms', 'self::span[@class="ms"]'); 404 405 // Layout elements. 406 defineRuleAlias('mrow', 'self::span[@class="mrow"]'); 407 408 // The following rules fix bugs in MathJax's LaTeX translation. 409 defineRuleAlias( 410 'mj-msub', 'self::span[@class="msubsup"]', 'CQFmathmlmsub'); 411 412 defineRuleAlias( 413 'mj-msup', 'self::span[@class="msubsup"]', 'CQFmathmlmsup'); 414 415 defineRuleAlias( 416 'mj-munder', 'self::span[@class="munderover"]', 'CQFmathmlmunder'); 417 418 defineRuleAlias( 419 'mj-mover', 'self::span[@class="munderover"]', 'CQFmathmlmover'); 420}; 421 422 423/** 424 * Initialize specializations wrt. content of nodes. 425 * @private 426 */ 427cvox.MathmlStoreRules.initSpecializationRules_ = function() { 428 // Some special nodes for square and cube. 429 // MathML 430 defineRule( 431 'square', 'default.default', 432 '[n] ./*[1]; [t] "square" (pitch:0.35); [p] (pause:300)', 433 'self::mathml:msup', './*[2][text()=2]'); 434 defineRuleAlias( 435 'square', 'self::mathml:msup', 436 './mathml:mrow=./*[2]', 'count(./*[2]/*)=1', './*[2]/*[1][text()=2]'); 437 438 defineRule( 439 'cube', 'default.default', 440 '[n] ./*[1]; [t] "cube" (pitch:0.35); [p] (pause:300)', 441 'self::mathml:msup', './*[2][text()=3]'); 442 defineRuleAlias( 443 'cube', 'self::mathml:msup', 444 './mathml:mrow=./*[2]', 'count(./*[2]/*)=1', './*[2]/*[1][text()=3]'); 445 446 defineRule( 447 'square-sub', 'default.default', 448 '[n] ./*[1]; [t] "sub"; [n] ./*[2] (pitch:-0.35);' + 449 '[p] (pause:300); [t] "square" (pitch:0.35); [p] (pause:400)', 450 'self::mathml:msubsup', './*[3][text()=2]'); 451 defineRuleAlias( 452 'square-sub', 'self::mathml:msubsup', 453 './mathml:mrow=./*[3]', 'count(./*[3]/*)=1', './*[3]/*[1][text()=2]'); 454 455 defineRule( 456 'cube-sub', 'default.default', 457 '[n] ./*[1]; [t] "sub"; [n] ./*[2] (pitch:-0.35);' + 458 '[p] (pause:300); [t] "cube" (pitch:0.35); [p] (pause:400)', 459 'self::mathml:msubsup', './*[3][text()=3]'); 460 defineRuleAlias( 461 'cube-sub', 'self::mathml:msubsup', 462 './mathml:mrow=./*[3]', 'count(./*[3]/*)=1', './*[3]/*[1][text()=3]'); 463 464 // MathJax 465 defineRule( 466 'mj-square', 'default.default', 467 '[n] ./*[1]/*[1]/*[1]; [t] "square" (pitch:0.35); [p] (pause:300)', 468 'self::span[@class="msup"]', './*[1]/*[2]/*[1][text()=2]'); 469 defineRuleAlias( 470 'mj-square', 'self::span[@class="msup"]', 471 './*[1]/*[2]/*[1]=./*[1]/*[2]/span[@class="mrow"]', 472 'count(./*[1]/*[2]/*[1]/*)=1', './*[1]/*[2]/*[1]/*[1][text()=2]'); 473 defineRuleAlias( 474 'mj-square', 'self::span[@class="msubsup"]', 'CQFmathmlmsup', 475 './*[1]/*[2]/*[1][text()=2]'); 476 defineRuleAlias( 477 'mj-square', 'self::span[@class="msubsup"]', 'CQFmathmlmsup', 478 './*[1]/*[2]/*[1]=./*[1]/*[2]/span[@class="mrow"]', 479 'count(./*[1]/*[2]/*[1]/*)=1', './*[1]/*[2]/*[1]/*[1][text()=2]'); 480 481 defineRule( 482 'mj-cube', 'default.default', 483 '[n] ./*[1]/*[1]/*[1]; [t] "cube" (pitch:0.35); [p] (pause:300)', 484 'self::span[@class="msup"]', './*[1]/*[2]/*[1][text()=3]'); 485 defineRuleAlias( 486 'mj-cube', 'self::span[@class="msup"]', 487 './*[1]/*[2]/*[1]=./*[1]/*[2]/span[@class="mrow"]', 488 'count(./*[1]/*[2]/*[1]/*)=1', './*[1]/*[2]/*[1]/*[1][text()=3]'); 489 defineRuleAlias( 490 'mj-cube', 'self::span[@class="msubsup"]', 'CQFmathmlmsup', 491 './*[1]/*[2]/*[1][text()=3]'); 492 defineRuleAlias( 493 'mj-cube', 'self::span[@class="msubsup"]', 'CQFmathmlmsup', 494 './*[1]/*[2]/*[1]=./*[1]/*[2]/span[@class="mrow"]', 495 'count(./*[1]/*[2]/*[1]/*)=1', './*[1]/*[2]/*[1]/*[1][text()=3]'); 496 497 defineRule( 498 'mj-square-sub', 'default.default', 499 '[n] ./*[1]/*[1]/*[1]; [t] "sub"; [n] ./*[1]/*[3]/*[1] (pitch:-0.35); ' + 500 '[p] (pause:300); [t] "square" (pitch:0.35); [p] (pause:400)', 501 'self::span[@class="msubsup"]', './*[1]/*[2]/*[1][text()=2]'); 502 defineRuleAlias( 503 'mj-square-sub', 'self::span[@class="msubsup"]', 504 './*[1]/*[2]/*[1]=./*[1]/*[2]/span[@class="mrow"]', 505 'count(./*[1]/*[2]/*[1]/*)=1', './*[1]/*[2]/*[1]/*[1][text()=2]'); 506 507 defineRule( 508 'mj-cube-sub', 'default.default', 509 '[n] ./*[1]/*[1]/*[1]; [t] "sub"; [n] ./*[1]/*[3]/*[1] (pitch:-0.35); ' + 510 '[p] (pause:300); [t] "cube" (pitch:0.35); [p] (pause:400)', 511 'self::span[@class="msubsup"]', './*[1]/*[2]/*[1][text()=3]'); 512 defineRuleAlias( 513 'mj-cube-sub', 'self::span[@class="msubsup"]', 514 './*[1]/*[2]/*[1]=./*[1]/*[2]/span[@class="mrow"]', 515 'count(./*[1]/*[2]/*[1]/*)=1', './*[1]/*[2]/*[1]/*[1][text()=3]'); 516}; 517 518 519/** 520 * Initialize mathJax Aliases 521 * @private 522 */ 523cvox.MathmlStoreRules.initSemanticRules_ = function() { 524 // Initial rule 525 defineRule( 526 'stree', 'default.default', 527 '[n] ./*[1]', 'self::stree'); 528 529 defineRule( 530 'multrel', 'default.default', 531 '[t] "multirelation"; [m] children/* (sepFunc:CTXFcontentIterator)', 532 'self::multirel'); 533 534 defineRule( 535 'variable-equality', 'default.default', 536 '[t] "equation sequence"; [m] ./children/* ' + 537 '(context:"part",ctxtFunc:CTXFnodeCounter,separator:./text())', 538 'self::relseq[@role="equality"]', 'count(./children/*)>2', 539 './children/punct[@role="ellipsis"]');// Make that better! 540 541 defineRule( 542 'multi-equality', 'default.default', 543 '[t] "equation sequence"; [m] ./children/* ' + 544 '(context:"part",ctxtFunc:CTXFnodeCounter,separator:./text())', 545 'self::relseq[@role="equality"]', 'count(./children/*)>2'); 546 547 defineRule( 548 'multi-equality', 'default.short', 549 '[t] "equation sequence"; [m] ./children/* ' + 550 '(separator:./text())', 551 'self::relseq[@role="equality"]', 'count(./children/*)>2'); 552 553 defineRule( 554 'equality', 'default.default', 555 '[t] "equation"; [t] "left hand side"; [n] children/*[1];' + 556 '[p] (pause:200); [n] text() (pause:200);' + 557 '[t] "right hand side"; [n] children/*[2]', 558 'self::relseq[@role="equality"]', 'count(./children/*)=2'); 559 560 defineRule( 561 'simple-equality', 'default.default', 562 '[n] children/*[1]; [p] (pause:200); [n] text() (pause:200);' + 563 '[n] children/*[2]', 564 'self::relseq[@role="equality"]', 'count(./children/*)=2', 565 './children/identifier or ./children/number'); 566 567 defineRule( 568 'simple-equality2', 'default.default', 569 '[n] children/*[1]; [p] (pause:200); [n] text() (pause:200);' + 570 '[n] children/*[2]', 571 'self::relseq[@role="equality"]', 'count(./children/*)=2', 572 './children/function or ./children/appl'); 573 574 defineRule( 575 'multrel', 'default.default', 576 '[m] children/* (separator:./text())', 577 'self::relseq'); 578 579 defineRule( 580 'binary-operation', 'default.default', 581 '[m] children/* (separator:text());', 582 'self::infixop'); 583 584 defineRule( 585 'variable-addition', 'default.default', 586 '[t] "sum with variable number of summands";' + 587 '[p] (pause:400); [m] children/* (separator:./text())', 588 'self::infixop[@role="addition"]', 'count(children/*)>2', 589 'children/punct[@role="ellipsis"]');// Make that better! 590 591 defineRule( 592 'multi-addition', 'default.default', 593 '[t] "sum with,"; [t] count(./children/*); [t] ", summands";' + 594 '[p] (pause:400); [m] ./children/* (separator:./text())', 595 'self::infixop[@role="addition"]', 'count(./children/*)>2'); 596 597 // Prefix Operator 598 defineRule( 599 'prefix', 'default.default', 600 '[t] "prefix"; [n] text(); [t] "of" (pause 150);' + 601 '[n] children/*[1]', 602 'self::prefixop'); 603 604 defineRule( 605 'negative', 'default.default', 606 '[t] "negative"; [n] children/*[1]', 607 'self::prefixop', 'self::prefixop[@role="negative"]'); 608 609 // Postfix Operator 610 defineRule( 611 'postfix', 'default.default', 612 '[n] children/*[1]; [t] "postfix"; [n] text() (pause 300)', 613 'self::postfixop'); 614 615 defineRule( 616 'identifier', 'default.default', 617 '[n] text()', 'self::identifier'); 618 619 defineRule( 620 'number', 'default.default', 621 '[n] text()', 'self::number'); 622 623 defineRule( 624 'fraction', 'default.default', 625 '[p] (pause:250); [n] children/*[1] (pitch:0.3); [p] (pause:250);' + 626 ' [t] "divided by"; [n] children/*[2] (pitch:-0.3); [p] (pause:400)', 627 'self::fraction'); 628 629 defineRule( 630 'superscript', 'default.default', 631 '[n] children/*[1]; [t] "super"; [n] children/*[2] (pitch:0.35);' + 632 '[p] (pause:300)', 633 'self::superscript'); 634 defineRule( 635 'subscript', 'default.default', 636 '[n] children/*[1]; [t] "sub"; [n] children/*[2] (pitch:-0.35);' + 637 '[p] (pause:300)', 638 'self::subscript'); 639 640 defineRule( 641 'ellipsis', 'default.default', 642 '[p] (pause:200); [t] "dot dot dot"; [p] (pause:300)', 643 'self::punct', 'self::punct[@role="ellipsis"]'); 644 645 defineRule( 646 'fence-single', 'default.default', 647 '[n] text()', 648 'self::punct', 'self::punct[@role="openfence"]'); 649 defineRuleAlias('fence-single', 'self::punct', 650 'self::punct[@role="closefence"]'); 651 defineRuleAlias('fence-single', 'self::punct', 652 'self::punct[@role="vbar"]'); 653 defineRuleAlias('fence-single', 'self::punct', 654 'self::punct[@role="application"]'); 655 656 // TODO (sorge) Refine punctuations further. 657 defineRule( 658 'omit-punct', 'default.default', 659 '[p] (pause:200);', 660 'self::punct'); 661 662 defineRule( 663 'omit-empty', 'default.default', 664 '', 665 'self::empty'); 666 667 // Fences rules. 668 defineRule( 669 'fences-open-close', 'default.default', 670 '[p] (pause:100); [t] "open"; [n] children/*[1]; [p] (pause:200);' + 671 '[t] "close"', 672 'self::fenced[@role="leftright"]'); 673 674 defineRule( 675 'fences-open-close-in-appl', 'default.default', 676 '[p] (pause:100); [n] children/*[1]; [p] (pause:200);', 677 'self::fenced[@role="leftright"]', './parent::children/parent::appl'); 678 679 defineRule( 680 'fences-neutral', 'default.default', 681 '[p] (pause:100); [t] "absolute value of"; [n] children/*[1];' + 682 '[p] (pause:350);', 683 'self::fenced', 'self::fenced[@role="neutral"]'); 684 685 defineRule( 686 'omit-fences', 'default.default', 687 '[p] (pause:500); [n] children/*[1]; [p] (pause:200);', 688 'self::fenced'); 689 690 // Matrix rules. 691 defineRule( 692 'matrix', 'default.default', 693 '[t] "matrix"; [m] children/* ' + 694 '(ctxtFunc:CTXFnodeCounter,context:"row",pause:100)', 695 'self::matrix'); 696 697 defineRule( 698 'matrix-row', 'default.default', 699 '[m] children/* (ctxtFunc:CTXFnodeCounter,context:"column",pause:100)', 700 'self::row[@role="matrix"]'); 701 702 defineRule( 703 'matrix-cell', 'default.default', 704 '[n] children/*[1]', 'self::cell[@role="matrix"]'); 705 706 // Vector rules. 707 defineRule( 708 'vector', 'default.default', 709 '[t] "vector"; [m] children/* ' + 710 '(ctxtFunc:CTXFnodeCounter,context:"element",pause:100)', 711 'self::vector'); 712 713 // Cases rules. 714 defineRule( 715 'cases', 'default.default', 716 '[t] "case statement"; [m] children/* ' + 717 '(ctxtFunc:CTXFnodeCounter,context:"case",pause:100)', 718 'self::cases'); 719 720 defineRule( 721 'cases-row', 'default.default', 722 '[m] children/*', 'self::row[@role="cases"]'); 723 724 defineRule( 725 'cases-cell', 'default.default', 726 '[n] children/*[1]', 'self::cell[@role="cases"]'); 727 728 defineRule( 729 'row', 'default.default', 730 '[m] ./* (ctxtFunc:CTXFnodeCounter,context:"column",pause:100)', 731 'self::row"'); 732 733 defineRule( 734 'cases-end', 'default.default', 735 '[t] "case statement"; ' + 736 '[m] children/* (ctxtFunc:CTXFnodeCounter,context:"case",pause:100);' + 737 '[t] "end cases"', 738 'self::cases', 'following-sibling::*'); 739 740 // Multiline rules. 741 defineRule( 742 'multiline', 'default.default', 743 '[t] "multiline equation";' + 744 '[m] children/* (ctxtFunc:CTXFnodeCounter,context:"line",pause:100)', 745 'self::multiline'); 746 747 defineRule( 748 'line', 'default.default', 749 '[m] children/*', 'self::line'); 750 751 // Table rules. 752 defineRule( 753 'table', 'default.default', 754 '[t] "multiline equation";' + 755 '[m] children/* (ctxtFunc:CTXFnodeCounter,context:"row",pause:200)', 756 'self::table'); 757 758 defineRule( 759 'table-row', 'default.default', 760 '[m] children/* (pause:100)', 'self::row[@role="table"]'); 761 762 defineRuleAlias( 763 'cases-cell', 'self::cell[@role="table"]'); 764 765 766 // Rules for punctuated expressions. 767 defineRule( 768 'end-punct', 'default.default', 769 '[m] children/*; [p] (pause:300)', 770 'self::punctuated', '@role="endpunct"'); 771 772 defineRule( 773 'start-punct', 'default.default', 774 '[n] content/*[1]; [p] (pause:200); [m] children/*', 775 'self::punctuated', '@role="startpunct"'); 776 777 defineRule( 778 'integral-punct', 'default.default', 779 '[n] children/*[1] (rate:0.2); [n] children/*[3] (rate:0.2)', 780 'self::punctuated', '@role="integral"'); 781 782 defineRule( 783 'punctuated', 'default.default', 784 '[m] children/* (pause:100)', 785 'self::punctuated'); 786 787 // Function rules 788 defineRule( 789 'function', 'default.default', 790 '[n] text()', 'self::function'); 791 792 defineRule( 793 'appl', 'default.default', 794 '[n] children/*[1]; [n] content/*[1]; [n] children/*[2]', 'self::appl'); 795 796 // Limit operator rules 797 defineRule( 798 'limboth', 'default.default', 799 '[n] children/*[1]; [t] "from"; [n] children/*[2]; [t] "to";' + 800 '[n] children/*[3]', 'self::limboth'); 801 802 defineRule( 803 'sum-only', 'default.default', 804 '[n] children/*[1]; [p] (pause 100); [t] "over"; [n] children/*[2];' + 805 '[p] (pause 250);', 806 'self::limboth', 'self::limboth[@role="sum"]'); 807 808 defineRule( 809 'limlower', 'default.default', 810 '[n] children/*[1]; [t] "over"; [n] children/*[2];', 'self::limlower'); 811 812 defineRule( 813 'limupper', 'default.default', 814 '[n] children/*[1]; [t] "under"; [n] children/*[2];', 'self::limupper'); 815 816 // Bigoperator rules 817 defineRule( 818 'largeop', 'default.default', 819 '[n] text()', 'self::largeop'); 820 821 defineRule( 822 'bigop', 'default.default', 823 '[n] children/*[1]; [p] (pause 100); [t] "over"; [n] children/*[2];' + 824 '[p] (pause 250);', 825 'self::bigop'); 826 827 828 // Integral rules 829 defineRule( 830 'integral', 'default.default', 831 '[n] children/*[1]; [p] (pause 100); [n] children/*[2]; [p] (pause 200);' + 832 '[n] children/*[3] (rate:0.35);', 'self::integral'); 833 834 835 defineRule( 836 'sqrt', 'default.default', 837 '[t] "Square root of"; [n] children/*[1] (rate:0.2); [p] (pause:400)', 838 'self::sqrt'); 839 840 defineRule( 841 'square', 'default.default', 842 '[n] children/*[1]; [t] "square" (pitch:0.35); [p] (pause:300)', 843 'self::superscript', 'children/*[2][text()=2]'); 844 845 defineRule( 846 'text-no-mult', 'default.default', 847 '[n] children/*[1]; [p] (pause:200); [n] children/*[2]', 848 'self::infixop', 'children/text'); 849}; 850 851}); // goog.scope 852