UNPKG

elliptical

Version:

Interactive natural-language interfaces

138 lines (114 loc) 4.36 kB
'use strict'; Object.defineProperty(exports, "__esModule", { value: true }); var _lodash = require('lodash'); var _lodash2 = _interopRequireDefault(_lodash); var _utils = require('../utils'); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } function* visit(option, _ref, traverse) { var _ref$props$unique = _ref.props.unique; let unique = _ref$props$unique === undefined ? false : _ref$props$unique; let children = _ref.children; const mods = { result: {}, score: 1 }; const trueOption = _lodash2.default.assign({}, option, mods); if (children.length) { const iterator = parseChildControl(0, trueOption, unique, children, traverse); yield* iterator; } } function shouldDoEllipsis(index, option, children) { // Don't do ellipsis for the first element, // or if this element is both optional and ellipsis, and the text is '' // because that results in duplicate options output const child = children[index]; return index > 0 && children[index - 1].props.ellipsis && !(child.props.ellipsis && child.props.optional && option.text === ''); } function* optionalTraversals(index, option, unique, children, traverse) { const child = children[index]; const withChildParse = parseChild(index, option, unique, children, traverse); const withoutChildParse = parseChildControl(index + 1, option, unique, children, traverse); // yield * limitIterator(optionals, child.props.limited ? 1 : undefined) if (child.props.preferred) { yield withChildParse; yield withoutChildParse; } else { yield withoutChildParse; yield withChildParse; } } function* parseChildControl(index, option, unique, children, traverse) { if (index >= children.length) { // we've reached the end yield option; return; } const child = children[index]; if (shouldDoEllipsis(index, option, children)) { if (option.text === '') { yield option; } else { let success = false; yield _lodash2.default.assign({}, option, { callbacks: option.callbacks.concat(() => { success = true; }) }); if (success) return; } } if (child.props.optional) { yield* (0, _utils.limitIterator)(optionalTraversals(index, option, unique, children, traverse), child.props.limited ? 1 : undefined); } else { yield* parseChild(index, option, unique, children, traverse); } } function hasSomeSameKeys(option, output) { const sameKeys = _lodash2.default.intersection(_lodash2.default.keys(option.result), _lodash2.default.keys(output.result)); return !_lodash2.default.isEmpty(sameKeys); } function* parseChild(index, option, unique, children, traverse) { const child = children[index]; const childOption = _lodash2.default.assign({}, option, { qualifiers: [], annotations: [], categories: [], arguments: [] }); for (let output of traverse(child, childOption)) { if (unique && output.result != null) { if (child.props.id && option.result[child.props.id] != null) { continue; } else if (child.props.merge && hasSomeSameKeys(option, output)) { continue; } } const modifications = { result: getAccumulatedResult(option.result, child, output.result), score: option.score * output.score, qualifiers: option.qualifiers.concat(output.qualifiers), annotations: option.annotations.concat(output.annotations), categories: option.categories.concat(output.categories), arguments: option.arguments.concat(output.arguments) }; let nextOutput = _lodash2.default.assign({}, output, modifications); yield* parseChildControl(index + 1, nextOutput, unique, children, traverse); } } function getAccumulatedResult(inputResult, child, childResult) { if (!_lodash2.default.isUndefined(childResult)) { const childId = child.props.id; const childMerge = child.props.merge; if (childId) { return _lodash2.default.assign({}, inputResult, { [childId]: childResult }); } else if (childMerge) { if (!_lodash2.default.isEmpty(inputResult) && _lodash2.default.isPlainObject(childResult)) { return _lodash2.default.merge({}, inputResult, childResult); } else { return childResult; } } } return inputResult; } exports.default = { visit: visit };