speech-rule-engine
Version:
A standalone speech rule engine for XML structures, based on the original engine from ChromeVox.
285 lines • 11 kB
JavaScript
"use strict";
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
var desc = Object.getOwnPropertyDescriptor(m, k);
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
desc = { enumerable: true, get: function() { return m[k]; } };
}
Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
o["default"] = v;
});
var __importStar = (this && this.__importStar) || (function () {
var ownKeys = function(o) {
ownKeys = Object.getOwnPropertyNames || function (o) {
var ar = [];
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
return ar;
};
return ownKeys(o);
};
return function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
__setModuleDefault(result, mod);
return result;
};
})();
Object.defineProperty(exports, "__esModule", { value: true });
exports.SemanticSkeleton = void 0;
const BaseUtil = __importStar(require("../common/base_util.js"));
const XpathUtil = __importStar(require("../common/xpath_util.js"));
const enrich_attr_js_1 = require("../enrich_mathml/enrich_attr.js");
const semantic_meaning_js_1 = require("./semantic_meaning.js");
class SemanticSkeleton {
static fromTree(tree) {
return SemanticSkeleton.fromNode(tree.root);
}
static fromNode(node) {
return new SemanticSkeleton(SemanticSkeleton.fromNode_(node));
}
static fromString(skel) {
return new SemanticSkeleton(SemanticSkeleton.fromString_(skel));
}
static simpleCollapseStructure(strct) {
return typeof strct === 'number';
}
static contentCollapseStructure(strct) {
return (!!strct &&
!SemanticSkeleton.simpleCollapseStructure(strct) &&
strct[0] === 'c');
}
static interleaveIds(first, second) {
return BaseUtil.interleaveLists(SemanticSkeleton.collapsedLeafs(first), SemanticSkeleton.collapsedLeafs(second));
}
static collapsedLeafs(...args) {
const collapseStructure = (coll) => {
if (SemanticSkeleton.simpleCollapseStructure(coll)) {
return [coll];
}
coll = coll;
return SemanticSkeleton.contentCollapseStructure(coll[1])
? coll.slice(2)
: coll.slice(1);
};
return args.reduce((x, y) => x.concat(collapseStructure(y)), []);
}
static fromStructure(mml, tree, options) {
return new SemanticSkeleton(SemanticSkeleton.tree_(mml, tree.root, options));
}
static combineContentChildren(type, _role, content, children) {
switch (type) {
case semantic_meaning_js_1.SemanticType.RELSEQ:
case semantic_meaning_js_1.SemanticType.INFIXOP:
case semantic_meaning_js_1.SemanticType.MULTIREL:
return BaseUtil.interleaveLists(children, content);
case semantic_meaning_js_1.SemanticType.PREFIXOP:
return content.concat(children);
case semantic_meaning_js_1.SemanticType.POSTFIXOP:
return children.concat(content);
case semantic_meaning_js_1.SemanticType.MATRIX:
case semantic_meaning_js_1.SemanticType.VECTOR:
case semantic_meaning_js_1.SemanticType.FENCED:
children.unshift(content[0]);
children.push(content[1]);
return children;
case semantic_meaning_js_1.SemanticType.CASES:
children.unshift(content[0]);
return children;
case semantic_meaning_js_1.SemanticType.APPL:
return [children[0], content[0], children[1]];
case semantic_meaning_js_1.SemanticType.ROOT:
return [children[0], children[1]];
case semantic_meaning_js_1.SemanticType.ROW:
case semantic_meaning_js_1.SemanticType.LINE:
if (content.length) {
children.unshift(content[0]);
}
return children;
default:
return children;
}
}
static makeSexp_(struct) {
if (SemanticSkeleton.simpleCollapseStructure(struct)) {
return struct.toString();
}
if (SemanticSkeleton.contentCollapseStructure(struct)) {
return ('(' +
'c ' +
struct.slice(1).map(SemanticSkeleton.makeSexp_).join(' ') +
')');
}
return ('(' + struct.map(SemanticSkeleton.makeSexp_).join(' ') + ')');
}
static fromString_(skeleton) {
let str = skeleton.replace(/\(/g, '[');
str = str.replace(/\)/g, ']');
str = str.replace(/ /g, ',');
str = str.replace(/c/g, '"c"');
return JSON.parse(str);
}
static fromNode_(node) {
if (!node) {
return [];
}
const content = node.contentNodes;
let contentStructure;
if (content.length) {
contentStructure = content.map(SemanticSkeleton.fromNode_);
contentStructure.unshift('c');
}
const children = node.childNodes;
if (!children.length) {
return content.length ? [node.id, contentStructure] : node.id;
}
const structure = children.map(SemanticSkeleton.fromNode_);
if (content.length) {
structure.unshift(contentStructure);
}
structure.unshift(node.id);
return structure;
}
static tree_(mml, node, options, level = 0, posinset = 1, setsize = 1) {
if (!node) {
return [];
}
const id = node.id;
const skeleton = [id];
XpathUtil.updateEvaluator(mml);
const mmlChild = XpathUtil.evalXPath(`.//self::*[@${enrich_attr_js_1.Attribute.ID}=${id}]`, mml)[0];
if (!node.childNodes.length) {
SemanticSkeleton.addAria(mmlChild, level, posinset, setsize, options);
return node.id;
}
const children = SemanticSkeleton.combineContentChildren(node.type, node.role, node.contentNodes.map(function (x) {
return x;
}), node.childNodes.map(function (x) {
return x;
}));
if (mmlChild) {
SemanticSkeleton.addOwns_(mmlChild, children);
}
for (let i = 0, l = children.length, child; (child = children[i]); i++) {
skeleton.push(SemanticSkeleton.tree_(mml, child, options, level + 1, i + 1, l));
}
SemanticSkeleton.addAria(mmlChild, level, posinset, setsize, options);
return skeleton;
}
static addAria(node, level, posinset, setsize, options) {
const role = !options.tree ? 'treeitem' : level ? 'treeitem' : 'tree';
if (!options.aria || !node) {
return;
}
node.setAttribute('aria-level', level.toString());
node.setAttribute('aria-posinset', posinset.toString());
node.setAttribute('aria-setsize', setsize.toString());
node.setAttribute('role', role);
if (node.hasAttribute(enrich_attr_js_1.Attribute.OWNS)) {
node.setAttribute('aria-owns', node.getAttribute(enrich_attr_js_1.Attribute.OWNS));
}
}
static addOwns_(node, children) {
const collapsed = node.getAttribute(enrich_attr_js_1.Attribute.COLLAPSED);
const leafs = collapsed
? SemanticSkeleton.realLeafs_(SemanticSkeleton.fromString(collapsed).array)
: children.map((x) => x.id);
node.setAttribute(enrich_attr_js_1.Attribute.OWNS, leafs.join(' '));
}
static realLeafs_(sexp) {
if (SemanticSkeleton.simpleCollapseStructure(sexp)) {
return [sexp];
}
if (SemanticSkeleton.contentCollapseStructure(sexp)) {
return [];
}
sexp = sexp;
let result = [];
for (let i = 1; i < sexp.length; i++) {
result = result.concat(SemanticSkeleton.realLeafs_(sexp[i]));
}
return result;
}
constructor(skeleton) {
this.parents = null;
this.levelsMap = null;
skeleton = skeleton === 0 ? skeleton : skeleton || [];
this.array = skeleton;
}
populate() {
if (this.parents && this.levelsMap) {
return;
}
this.parents = {};
this.levelsMap = {};
this.populate_(this.array, this.array, []);
}
toString() {
return SemanticSkeleton.makeSexp_(this.array);
}
populate_(element, layer, parents) {
if (SemanticSkeleton.simpleCollapseStructure(element)) {
element = element;
this.levelsMap[element] = layer;
this.parents[element] =
element === parents[0] ? parents.slice(1) : parents;
return;
}
const newElement = SemanticSkeleton.contentCollapseStructure(element)
? element.slice(1)
: element;
const newParents = [newElement[0]].concat(parents);
for (let i = 0, l = newElement.length; i < l; i++) {
const current = newElement[i];
this.populate_(current, element, newParents);
}
}
isRoot(id) {
const level = this.levelsMap[id];
return id === level[0];
}
directChildren(id) {
if (!this.isRoot(id)) {
return [];
}
const level = this.levelsMap[id];
return level.slice(1).map((child) => {
if (SemanticSkeleton.simpleCollapseStructure(child)) {
return child;
}
if (SemanticSkeleton.contentCollapseStructure(child)) {
return child[1];
}
return child[0];
});
}
subtreeNodes(id) {
if (!this.isRoot(id)) {
return [];
}
const subtreeNodes_ = (tree, nodes) => {
if (SemanticSkeleton.simpleCollapseStructure(tree)) {
nodes.push(tree);
return;
}
tree = tree;
if (SemanticSkeleton.contentCollapseStructure(tree)) {
tree = tree.slice(1);
}
tree.forEach((x) => subtreeNodes_(x, nodes));
};
const level = this.levelsMap[id];
const subtree = [];
subtreeNodes_(level.slice(1), subtree);
return subtree;
}
}
exports.SemanticSkeleton = SemanticSkeleton;
//# sourceMappingURL=semantic_skeleton.js.map