mathspeak_util.js 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482
  1. "use strict";
  2. Object.defineProperty(exports, "__esModule", { value: true });
  3. exports.spaceoutText = spaceoutText;
  4. exports.spaceoutNumber = spaceoutNumber;
  5. exports.spaceoutIdentifier = spaceoutIdentifier;
  6. exports.resetNestingDepth = resetNestingDepth;
  7. exports.fractionNestingDepth = fractionNestingDepth;
  8. exports.openingFractionVerbose = openingFractionVerbose;
  9. exports.closingFractionVerbose = closingFractionVerbose;
  10. exports.overFractionVerbose = overFractionVerbose;
  11. exports.openingFractionBrief = openingFractionBrief;
  12. exports.closingFractionBrief = closingFractionBrief;
  13. exports.openingFractionSbrief = openingFractionSbrief;
  14. exports.closingFractionSbrief = closingFractionSbrief;
  15. exports.overFractionSbrief = overFractionSbrief;
  16. exports.isSmallVulgarFraction = isSmallVulgarFraction;
  17. exports.nestedSubSuper = nestedSubSuper;
  18. exports.subscriptVerbose = subscriptVerbose;
  19. exports.subscriptBrief = subscriptBrief;
  20. exports.superscriptVerbose = superscriptVerbose;
  21. exports.superscriptBrief = superscriptBrief;
  22. exports.baselineVerbose = baselineVerbose;
  23. exports.baselineBrief = baselineBrief;
  24. exports.radicalNestingDepth = radicalNestingDepth;
  25. exports.openingRadicalVerbose = openingRadicalVerbose;
  26. exports.closingRadicalVerbose = closingRadicalVerbose;
  27. exports.indexRadicalVerbose = indexRadicalVerbose;
  28. exports.openingRadicalBrief = openingRadicalBrief;
  29. exports.closingRadicalBrief = closingRadicalBrief;
  30. exports.indexRadicalBrief = indexRadicalBrief;
  31. exports.openingRadicalSbrief = openingRadicalSbrief;
  32. exports.indexRadicalSbrief = indexRadicalSbrief;
  33. exports.nestedUnderscript = nestedUnderscript;
  34. exports.endscripts = endscripts;
  35. exports.nestedOverscript = nestedOverscript;
  36. exports.determinantIsSimple = determinantIsSimple;
  37. exports.generateBaselineConstraint = generateBaselineConstraint;
  38. exports.removeParens = removeParens;
  39. exports.generateTensorRules = generateTensorRules;
  40. exports.smallRoot = smallRoot;
  41. const span_js_1 = require("../audio/span.js");
  42. const BaseUtil = require("../common/base_util.js");
  43. const DomUtil = require("../common/dom_util.js");
  44. const XpathUtil = require("../common/xpath_util.js");
  45. const locale_js_1 = require("../l10n/locale.js");
  46. const semantic_meaning_js_1 = require("../semantic_tree/semantic_meaning.js");
  47. const semantic_processor_js_1 = require("../semantic_tree/semantic_processor.js");
  48. let nestingDepth = {};
  49. function spaceoutText(node) {
  50. return Array.from(node.textContent).map(span_js_1.Span.stringEmpty);
  51. }
  52. function spaceoutNodes(node, correction) {
  53. const content = Array.from(node.textContent);
  54. const result = [];
  55. const processor = semantic_processor_js_1.SemanticProcessor.getInstance();
  56. const doc = node.ownerDocument;
  57. for (let i = 0, chr; (chr = content[i]); i++) {
  58. const leaf = processor
  59. .getNodeFactory()
  60. .makeLeafNode(chr, semantic_meaning_js_1.SemanticFont.UNKNOWN);
  61. const sn = processor.identifierNode(leaf, semantic_meaning_js_1.SemanticFont.UNKNOWN, '');
  62. correction(sn);
  63. result.push(sn.xml(doc));
  64. }
  65. return result;
  66. }
  67. function spaceoutNumber(node) {
  68. return spaceoutNodes(node, function (sn) {
  69. if (!sn.textContent.match(/\W/)) {
  70. sn.type = semantic_meaning_js_1.SemanticType.NUMBER;
  71. }
  72. });
  73. }
  74. function spaceoutIdentifier(node) {
  75. return spaceoutNodes(node, function (sn) {
  76. sn.font = semantic_meaning_js_1.SemanticFont.UNKNOWN;
  77. sn.type = semantic_meaning_js_1.SemanticType.IDENTIFIER;
  78. });
  79. }
  80. const nestingBarriers = [
  81. semantic_meaning_js_1.SemanticType.CASES,
  82. semantic_meaning_js_1.SemanticType.CELL,
  83. semantic_meaning_js_1.SemanticType.INTEGRAL,
  84. semantic_meaning_js_1.SemanticType.LINE,
  85. semantic_meaning_js_1.SemanticType.MATRIX,
  86. semantic_meaning_js_1.SemanticType.MULTILINE,
  87. semantic_meaning_js_1.SemanticType.OVERSCORE,
  88. semantic_meaning_js_1.SemanticType.ROOT,
  89. semantic_meaning_js_1.SemanticType.ROW,
  90. semantic_meaning_js_1.SemanticType.SQRT,
  91. semantic_meaning_js_1.SemanticType.SUBSCRIPT,
  92. semantic_meaning_js_1.SemanticType.SUPERSCRIPT,
  93. semantic_meaning_js_1.SemanticType.TABLE,
  94. semantic_meaning_js_1.SemanticType.UNDERSCORE,
  95. semantic_meaning_js_1.SemanticType.VECTOR
  96. ];
  97. function resetNestingDepth(node) {
  98. nestingDepth = {};
  99. return [node];
  100. }
  101. function getNestingDepth(type, node, tags, opt_barrierTags, opt_barrierAttrs, opt_func) {
  102. opt_barrierTags = opt_barrierTags || nestingBarriers;
  103. opt_barrierAttrs = opt_barrierAttrs || {};
  104. opt_func =
  105. opt_func ||
  106. function (_node) {
  107. return false;
  108. };
  109. const xmlText = DomUtil.serializeXml(node);
  110. if (!nestingDepth[type]) {
  111. nestingDepth[type] = {};
  112. }
  113. if (nestingDepth[type][xmlText]) {
  114. return nestingDepth[type][xmlText];
  115. }
  116. if (opt_func(node) || tags.indexOf(node.tagName) < 0) {
  117. return 0;
  118. }
  119. const depth = computeNestingDepth_(node, tags, BaseUtil.setdifference(opt_barrierTags, tags), opt_barrierAttrs, opt_func, 0);
  120. nestingDepth[type][xmlText] = depth;
  121. return depth;
  122. }
  123. function containsAttr(node, attrs) {
  124. if (!node.attributes) {
  125. return false;
  126. }
  127. const attributes = DomUtil.toArray(node.attributes);
  128. for (let i = 0, attr; (attr = attributes[i]); i++) {
  129. if (attrs[attr.nodeName] === attr.nodeValue) {
  130. return true;
  131. }
  132. }
  133. return false;
  134. }
  135. function computeNestingDepth_(node, tags, barriers, attrs, func, depth) {
  136. if (func(node) ||
  137. barriers.indexOf(node.tagName) > -1 ||
  138. containsAttr(node, attrs)) {
  139. return depth;
  140. }
  141. if (tags.indexOf(node.tagName) > -1) {
  142. depth++;
  143. }
  144. if (!node.childNodes || node.childNodes.length === 0) {
  145. return depth;
  146. }
  147. const children = DomUtil.toArray(node.childNodes);
  148. return Math.max.apply(null, children.map(function (subNode) {
  149. return computeNestingDepth_(subNode, tags, barriers, attrs, func, depth);
  150. }));
  151. }
  152. function fractionNestingDepth(node) {
  153. return getNestingDepth('fraction', node, ['fraction'], nestingBarriers, {}, locale_js_1.LOCALE.FUNCTIONS.fracNestDepth);
  154. }
  155. function nestedFraction(node, expr, opt_end) {
  156. const depth = fractionNestingDepth(node);
  157. const annotation = Array(depth).fill(expr);
  158. if (opt_end) {
  159. annotation.push(opt_end);
  160. }
  161. return annotation.join(locale_js_1.LOCALE.MESSAGES.regexp.JOINER_FRAC);
  162. }
  163. function openingFractionVerbose(node) {
  164. return span_js_1.Span.singleton(nestedFraction(node, locale_js_1.LOCALE.MESSAGES.MS.START, locale_js_1.LOCALE.MESSAGES.MS.FRAC_V));
  165. }
  166. function closingFractionVerbose(node) {
  167. return span_js_1.Span.singleton(nestedFraction(node, locale_js_1.LOCALE.MESSAGES.MS.END, locale_js_1.LOCALE.MESSAGES.MS.FRAC_V), { kind: 'LAST' });
  168. }
  169. function overFractionVerbose(node) {
  170. return span_js_1.Span.singleton(nestedFraction(node, locale_js_1.LOCALE.MESSAGES.MS.FRAC_OVER), {});
  171. }
  172. function openingFractionBrief(node) {
  173. return span_js_1.Span.singleton(nestedFraction(node, locale_js_1.LOCALE.MESSAGES.MS.START, locale_js_1.LOCALE.MESSAGES.MS.FRAC_B));
  174. }
  175. function closingFractionBrief(node) {
  176. return span_js_1.Span.singleton(nestedFraction(node, locale_js_1.LOCALE.MESSAGES.MS.END, locale_js_1.LOCALE.MESSAGES.MS.FRAC_B), { kind: 'LAST' });
  177. }
  178. function openingFractionSbrief(node) {
  179. const depth = fractionNestingDepth(node);
  180. return span_js_1.Span.singleton(depth === 1
  181. ? locale_js_1.LOCALE.MESSAGES.MS.FRAC_S
  182. : locale_js_1.LOCALE.FUNCTIONS.combineNestedFraction(locale_js_1.LOCALE.MESSAGES.MS.NEST_FRAC, locale_js_1.LOCALE.FUNCTIONS.radicalNestDepth(depth - 1), locale_js_1.LOCALE.MESSAGES.MS.FRAC_S));
  183. }
  184. function closingFractionSbrief(node) {
  185. const depth = fractionNestingDepth(node);
  186. return span_js_1.Span.singleton(depth === 1
  187. ? locale_js_1.LOCALE.MESSAGES.MS.ENDFRAC
  188. : locale_js_1.LOCALE.FUNCTIONS.combineNestedFraction(locale_js_1.LOCALE.MESSAGES.MS.NEST_FRAC, locale_js_1.LOCALE.FUNCTIONS.radicalNestDepth(depth - 1), locale_js_1.LOCALE.MESSAGES.MS.ENDFRAC), { kind: 'LAST' });
  189. }
  190. function overFractionSbrief(node) {
  191. const depth = fractionNestingDepth(node);
  192. return span_js_1.Span.singleton(depth === 1
  193. ? locale_js_1.LOCALE.MESSAGES.MS.FRAC_OVER
  194. : locale_js_1.LOCALE.FUNCTIONS.combineNestedFraction(locale_js_1.LOCALE.MESSAGES.MS.NEST_FRAC, locale_js_1.LOCALE.FUNCTIONS.radicalNestDepth(depth - 1), locale_js_1.LOCALE.MESSAGES.MS.FRAC_OVER));
  195. }
  196. function isSmallVulgarFraction(node) {
  197. return locale_js_1.LOCALE.FUNCTIONS.fracNestDepth(node) ? [node] : [];
  198. }
  199. function nestedSubSuper(node, init, replace) {
  200. while (node.parentNode) {
  201. const children = node.parentNode;
  202. const parent = children.parentNode;
  203. if (!parent) {
  204. break;
  205. }
  206. const nodeRole = node.getAttribute && node.getAttribute('role');
  207. if ((parent.tagName === semantic_meaning_js_1.SemanticType.SUBSCRIPT &&
  208. node === children.childNodes[1]) ||
  209. (parent.tagName === semantic_meaning_js_1.SemanticType.TENSOR &&
  210. nodeRole &&
  211. (nodeRole === semantic_meaning_js_1.SemanticRole.LEFTSUB ||
  212. nodeRole === semantic_meaning_js_1.SemanticRole.RIGHTSUB))) {
  213. init = replace.sub + locale_js_1.LOCALE.MESSAGES.regexp.JOINER_SUBSUPER + init;
  214. }
  215. if ((parent.tagName === semantic_meaning_js_1.SemanticType.SUPERSCRIPT &&
  216. node === children.childNodes[1]) ||
  217. (parent.tagName === semantic_meaning_js_1.SemanticType.TENSOR &&
  218. nodeRole &&
  219. (nodeRole === semantic_meaning_js_1.SemanticRole.LEFTSUPER ||
  220. nodeRole === semantic_meaning_js_1.SemanticRole.RIGHTSUPER))) {
  221. init = replace.sup + locale_js_1.LOCALE.MESSAGES.regexp.JOINER_SUBSUPER + init;
  222. }
  223. node = parent;
  224. }
  225. return init.trim();
  226. }
  227. function subscriptVerbose(node) {
  228. return span_js_1.Span.singleton(nestedSubSuper(node, locale_js_1.LOCALE.MESSAGES.MS.SUBSCRIPT, {
  229. sup: locale_js_1.LOCALE.MESSAGES.MS.SUPER,
  230. sub: locale_js_1.LOCALE.MESSAGES.MS.SUB
  231. }));
  232. }
  233. function subscriptBrief(node) {
  234. return span_js_1.Span.singleton(nestedSubSuper(node, locale_js_1.LOCALE.MESSAGES.MS.SUB, {
  235. sup: locale_js_1.LOCALE.MESSAGES.MS.SUP,
  236. sub: locale_js_1.LOCALE.MESSAGES.MS.SUB
  237. }));
  238. }
  239. function superscriptVerbose(node) {
  240. return span_js_1.Span.singleton(nestedSubSuper(node, locale_js_1.LOCALE.MESSAGES.MS.SUPERSCRIPT, {
  241. sup: locale_js_1.LOCALE.MESSAGES.MS.SUPER,
  242. sub: locale_js_1.LOCALE.MESSAGES.MS.SUB
  243. }));
  244. }
  245. function superscriptBrief(node) {
  246. return span_js_1.Span.singleton(nestedSubSuper(node, locale_js_1.LOCALE.MESSAGES.MS.SUP, {
  247. sup: locale_js_1.LOCALE.MESSAGES.MS.SUP,
  248. sub: locale_js_1.LOCALE.MESSAGES.MS.SUB
  249. }));
  250. }
  251. function baselineVerbose(node) {
  252. const baseline = nestedSubSuper(node, '', {
  253. sup: locale_js_1.LOCALE.MESSAGES.MS.SUPER,
  254. sub: locale_js_1.LOCALE.MESSAGES.MS.SUB
  255. });
  256. return span_js_1.Span.singleton(!baseline
  257. ? locale_js_1.LOCALE.MESSAGES.MS.BASELINE
  258. : baseline
  259. .replace(new RegExp(locale_js_1.LOCALE.MESSAGES.MS.SUB + '$'), locale_js_1.LOCALE.MESSAGES.MS.SUBSCRIPT)
  260. .replace(new RegExp(locale_js_1.LOCALE.MESSAGES.MS.SUPER + '$'), locale_js_1.LOCALE.MESSAGES.MS.SUPERSCRIPT));
  261. }
  262. function baselineBrief(node) {
  263. const baseline = nestedSubSuper(node, '', {
  264. sup: locale_js_1.LOCALE.MESSAGES.MS.SUP,
  265. sub: locale_js_1.LOCALE.MESSAGES.MS.SUB
  266. });
  267. return span_js_1.Span.singleton(baseline || locale_js_1.LOCALE.MESSAGES.MS.BASE);
  268. }
  269. function radicalNestingDepth(node) {
  270. return getNestingDepth('radical', node, ['sqrt', 'root'], nestingBarriers, {});
  271. }
  272. function nestedRadical(node, prefix, postfix) {
  273. const depth = radicalNestingDepth(node);
  274. const index = getRootIndex(node);
  275. postfix = index ? locale_js_1.LOCALE.FUNCTIONS.combineRootIndex(postfix, index) : postfix;
  276. return depth === 1
  277. ? postfix
  278. : locale_js_1.LOCALE.FUNCTIONS.combineNestedRadical(prefix, locale_js_1.LOCALE.FUNCTIONS.radicalNestDepth(depth - 1), postfix);
  279. }
  280. function getRootIndex(node) {
  281. const content = node.tagName === 'sqrt'
  282. ? '2'
  283. :
  284. XpathUtil.evalXPath('children/*[1]', node)[0].textContent.trim();
  285. return locale_js_1.LOCALE.MESSAGES.MSroots[content] || '';
  286. }
  287. function openingRadicalVerbose(node) {
  288. return span_js_1.Span.singleton(nestedRadical(node, locale_js_1.LOCALE.MESSAGES.MS.NESTED, locale_js_1.LOCALE.MESSAGES.MS.STARTROOT));
  289. }
  290. function closingRadicalVerbose(node) {
  291. return span_js_1.Span.singleton(nestedRadical(node, locale_js_1.LOCALE.MESSAGES.MS.NESTED, locale_js_1.LOCALE.MESSAGES.MS.ENDROOT));
  292. }
  293. function indexRadicalVerbose(node) {
  294. return span_js_1.Span.singleton(nestedRadical(node, locale_js_1.LOCALE.MESSAGES.MS.NESTED, locale_js_1.LOCALE.MESSAGES.MS.ROOTINDEX));
  295. }
  296. function openingRadicalBrief(node) {
  297. return span_js_1.Span.singleton(nestedRadical(node, locale_js_1.LOCALE.MESSAGES.MS.NEST_ROOT, locale_js_1.LOCALE.MESSAGES.MS.STARTROOT));
  298. }
  299. function closingRadicalBrief(node) {
  300. return span_js_1.Span.singleton(nestedRadical(node, locale_js_1.LOCALE.MESSAGES.MS.NEST_ROOT, locale_js_1.LOCALE.MESSAGES.MS.ENDROOT));
  301. }
  302. function indexRadicalBrief(node) {
  303. return span_js_1.Span.singleton(nestedRadical(node, locale_js_1.LOCALE.MESSAGES.MS.NEST_ROOT, locale_js_1.LOCALE.MESSAGES.MS.ROOTINDEX));
  304. }
  305. function openingRadicalSbrief(node) {
  306. return span_js_1.Span.singleton(nestedRadical(node, locale_js_1.LOCALE.MESSAGES.MS.NEST_ROOT, locale_js_1.LOCALE.MESSAGES.MS.ROOT));
  307. }
  308. function indexRadicalSbrief(node) {
  309. return span_js_1.Span.singleton(nestedRadical(node, locale_js_1.LOCALE.MESSAGES.MS.NEST_ROOT, locale_js_1.LOCALE.MESSAGES.MS.INDEX));
  310. }
  311. function underscoreNestingDepth(node) {
  312. return getNestingDepth('underscore', node, ['underscore'], nestingBarriers, {}, function (node) {
  313. return (node.tagName &&
  314. node.tagName === semantic_meaning_js_1.SemanticType.UNDERSCORE &&
  315. node.childNodes[0].childNodes[1].getAttribute('role') ===
  316. semantic_meaning_js_1.SemanticRole.UNDERACCENT);
  317. });
  318. }
  319. function nestedUnderscript(node) {
  320. const depth = underscoreNestingDepth(node);
  321. return span_js_1.Span.singleton(Array(depth).join(locale_js_1.LOCALE.MESSAGES.MS.UNDER) + locale_js_1.LOCALE.MESSAGES.MS.UNDERSCRIPT);
  322. }
  323. function overscoreNestingDepth(node) {
  324. return getNestingDepth('overscore', node, ['overscore'], nestingBarriers, {}, function (node) {
  325. return (node.tagName &&
  326. node.tagName === semantic_meaning_js_1.SemanticType.OVERSCORE &&
  327. node.childNodes[0].childNodes[1].getAttribute('role') ===
  328. semantic_meaning_js_1.SemanticRole.OVERACCENT);
  329. });
  330. }
  331. function endscripts(_node) {
  332. return span_js_1.Span.singleton(locale_js_1.LOCALE.MESSAGES.MS.ENDSCRIPTS);
  333. }
  334. function nestedOverscript(node) {
  335. const depth = overscoreNestingDepth(node);
  336. return span_js_1.Span.singleton(Array(depth).join(locale_js_1.LOCALE.MESSAGES.MS.OVER) + locale_js_1.LOCALE.MESSAGES.MS.OVERSCRIPT);
  337. }
  338. function determinantIsSimple(node) {
  339. if (node.tagName !== semantic_meaning_js_1.SemanticType.MATRIX ||
  340. node.getAttribute('role') !== semantic_meaning_js_1.SemanticRole.DETERMINANT) {
  341. return [];
  342. }
  343. const cells = XpathUtil.evalXPath('children/row/children/cell/children/*', node);
  344. for (let i = 0, cell; (cell = cells[i]); i++) {
  345. if (cell.tagName === semantic_meaning_js_1.SemanticType.NUMBER) {
  346. continue;
  347. }
  348. if (cell.tagName === semantic_meaning_js_1.SemanticType.IDENTIFIER) {
  349. const role = cell.getAttribute('role');
  350. if (role === semantic_meaning_js_1.SemanticRole.LATINLETTER ||
  351. role === semantic_meaning_js_1.SemanticRole.GREEKLETTER ||
  352. role === semantic_meaning_js_1.SemanticRole.OTHERLETTER) {
  353. continue;
  354. }
  355. }
  356. return [];
  357. }
  358. return [node];
  359. }
  360. function generateBaselineConstraint() {
  361. const ignoreElems = ['subscript', 'superscript', 'tensor'];
  362. const mainElems = ['relseq', 'multrel'];
  363. const breakElems = ['fraction', 'punctuation', 'fenced', 'sqrt', 'root'];
  364. const ancestrify = (elemList) => elemList.map((elem) => 'ancestor::' + elem);
  365. const notify = (elem) => 'not(' + elem + ')';
  366. const prefix = 'ancestor::*/following-sibling::*';
  367. const middle = notify(ancestrify(ignoreElems).join(' or '));
  368. const mainList = ancestrify(mainElems);
  369. const breakList = ancestrify(breakElems);
  370. let breakCstrs = [];
  371. for (let i = 0, brk; (brk = breakList[i]); i++) {
  372. breakCstrs = breakCstrs.concat(mainList.map(function (elem) {
  373. return brk + '/' + elem;
  374. }));
  375. }
  376. const postfix = notify(breakCstrs.join(' | '));
  377. return [[prefix, middle, postfix].join(' and ')];
  378. }
  379. function removeParens(node) {
  380. if (!node.childNodes.length ||
  381. !node.childNodes[0].childNodes.length ||
  382. !node.childNodes[0].childNodes[0].childNodes.length) {
  383. return span_js_1.Span.singleton('');
  384. }
  385. const content = node.childNodes[0].childNodes[0].childNodes[0].textContent;
  386. return span_js_1.Span.singleton(content.match(/^\(.+\)$/) ? content.slice(1, -1) : content);
  387. }
  388. const componentString = new Map([
  389. [3, 'CSFleftsuperscript'],
  390. [4, 'CSFleftsubscript'],
  391. [2, 'CSFbaseline'],
  392. [1, 'CSFrightsubscript'],
  393. [0, 'CSFrightsuperscript']
  394. ]);
  395. const childNumber = new Map([
  396. [4, 2],
  397. [3, 3],
  398. [2, 1],
  399. [1, 4],
  400. [0, 5]
  401. ]);
  402. function generateTensorRuleStrings_(constellation) {
  403. const constraints = [];
  404. let verbString = '';
  405. let briefString = '';
  406. let constel = parseInt(constellation, 2);
  407. for (let i = 0; i < 5; i++) {
  408. const childString = 'children/*[' + childNumber.get(i) + ']';
  409. if (constel & 1) {
  410. const compString = componentString.get(i % 5);
  411. verbString =
  412. '[t] ' + compString + 'Verbose; [n] ' + childString + ';' + verbString;
  413. briefString =
  414. '[t] ' + compString + 'Brief; [n] ' + childString + ';' + briefString;
  415. }
  416. else {
  417. constraints.unshift('name(' + childString + ')="empty"');
  418. }
  419. constel >>= 1;
  420. }
  421. return [constraints, verbString, briefString];
  422. }
  423. function generateTensorRules(store, brief = true) {
  424. const constellations = [
  425. '11111',
  426. '11110',
  427. '11101',
  428. '11100',
  429. '10111',
  430. '10110',
  431. '10101',
  432. '10100',
  433. '01111',
  434. '01110',
  435. '01101',
  436. '01100'
  437. ];
  438. for (const constel of constellations) {
  439. let name = 'tensor' + constel;
  440. let [components, verbStr, briefStr] = generateTensorRuleStrings_(constel);
  441. store.defineRule(name, 'default', verbStr, 'self::tensor', ...components);
  442. if (brief) {
  443. store.defineRule(name, 'brief', briefStr, 'self::tensor', ...components);
  444. store.defineRule(name, 'sbrief', briefStr, 'self::tensor', ...components);
  445. }
  446. if (!(parseInt(constel, 2) & 3)) {
  447. continue;
  448. }
  449. const baselineStr = componentString.get(2);
  450. verbStr += '; [t]' + baselineStr + 'Verbose';
  451. briefStr += '; [t]' + baselineStr + 'Brief';
  452. name = name + '-baseline';
  453. const cstr = '((.//*[not(*)])[last()]/@id)!=(((.//ancestor::fraction|' +
  454. 'ancestor::root|ancestor::sqrt|ancestor::cell|ancestor::line|' +
  455. 'ancestor::stree)[1]//*[not(*)])[last()]/@id)';
  456. store.defineRule(name, 'default', verbStr, 'self::tensor', cstr, ...components);
  457. if (brief) {
  458. store.defineRule(name, 'brief', briefStr, 'self::tensor', cstr, ...components);
  459. store.defineRule(name, 'sbrief', briefStr, 'self::tensor', cstr, ...components);
  460. }
  461. }
  462. }
  463. function smallRoot(node) {
  464. let max = Object.keys(locale_js_1.LOCALE.MESSAGES.MSroots).length;
  465. if (!max) {
  466. return [];
  467. }
  468. else {
  469. max++;
  470. }
  471. if (!node.childNodes ||
  472. node.childNodes.length === 0 ||
  473. !node.childNodes[0].childNodes) {
  474. return [];
  475. }
  476. const index = node.childNodes[0].childNodes[0].textContent;
  477. if (!/^\d+$/.test(index)) {
  478. return [];
  479. }
  480. const num = parseInt(index, 10);
  481. return num > 1 && num <= max ? [node] : [];
  482. }