idyll-ast
Version:
Utilities for manipulating Idyll's AST
1,025 lines (844 loc) • 38.7 kB
JavaScript
;
Object.defineProperty(exports, '__esModule', { value: true });
var _typeof = require('@babel/runtime/helpers/typeof');
var _objectWithoutProperties = require('@babel/runtime/helpers/objectWithoutProperties');
var _defineProperty = require('@babel/runtime/helpers/defineProperty');
var _createClass = require('@babel/runtime/helpers/createClass');
var _classCallCheck = require('@babel/runtime/helpers/classCallCheck');
var _inherits = require('@babel/runtime/helpers/inherits');
var _possibleConstructorReturn = require('@babel/runtime/helpers/possibleConstructorReturn');
var _getPrototypeOf = require('@babel/runtime/helpers/getPrototypeOf');
var _wrapNativeSuper = require('@babel/runtime/helpers/wrapNativeSuper');
var Ajv = require('ajv');
var htmlTags = require('html-tags');
function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'default' in e ? e : { 'default': e }; }
var _typeof__default = /*#__PURE__*/_interopDefaultLegacy(_typeof);
var _objectWithoutProperties__default = /*#__PURE__*/_interopDefaultLegacy(_objectWithoutProperties);
var _defineProperty__default = /*#__PURE__*/_interopDefaultLegacy(_defineProperty);
var _createClass__default = /*#__PURE__*/_interopDefaultLegacy(_createClass);
var _classCallCheck__default = /*#__PURE__*/_interopDefaultLegacy(_classCallCheck);
var _inherits__default = /*#__PURE__*/_interopDefaultLegacy(_inherits);
var _possibleConstructorReturn__default = /*#__PURE__*/_interopDefaultLegacy(_possibleConstructorReturn);
var _getPrototypeOf__default = /*#__PURE__*/_interopDefaultLegacy(_getPrototypeOf);
var _wrapNativeSuper__default = /*#__PURE__*/_interopDefaultLegacy(_wrapNativeSuper);
var Ajv__default = /*#__PURE__*/_interopDefaultLegacy(Ajv);
var htmlTags__default = /*#__PURE__*/_interopDefaultLegacy(htmlTags);
function _toPropertyKey(arg) { var key = _toPrimitive(arg, "string"); return _typeof__default["default"](key) === "symbol" ? key : String(key); }
function _toPrimitive(input, hint) { if (_typeof__default["default"](input) !== "object" || input === null) return input; var prim = input[Symbol.toPrimitive]; if (prim !== undefined) { var res = prim.call(input, hint || "default"); if (_typeof__default["default"](res) !== "object") return res; throw new TypeError("@@toPrimitive must return a primitive value."); } return (hint === "string" ? String : Number)(input); }
function ownKeys$1(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); enumerableOnly && (symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; })), keys.push.apply(keys, symbols); } return keys; }
function _objectSpread$1(target) { for (var i = 1; i < arguments.length; i++) { var source = null != arguments[i] ? arguments[i] : {}; i % 2 ? ownKeys$1(Object(source), !0).forEach(function (key) { _defineProperty__default["default"](target, key, source[key]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)) : ownKeys$1(Object(source)).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } return target; }
// -- Constants ----
/**
* Property type string for value-typed properties.
*/
var VALUE = 'value';
/**
* Property type string for variable-typed properties.
*/
var VARIABLE = 'variable';
/**
* Property type string for expression-typed properties.
*/
var EXPRESSION = 'expression';
/**
* Node type string for component nodes.
*/
var COMPONENT = 'component';
/**
* Node type string for text nodes.
*/
var TEXTNODE = 'textnode';
/**
* Node type string for var nodes.
*/
var VAR = 'var';
/**
* Node type string for derived nodes.
*/
var DERIVED = 'derived';
/**
* Node type string for data nodes.
*/
var DATA = 'data';
/**
* Node type string for meta nodes.
*/
var META = 'meta'; // -- AST Nodes ----
/**
* Create a new AST node.
* @param {string} name Name of the node.
* @param {string} type Type of the node.
* @param {object} props Properties of the node.
* @param {object[]} children Children of the node.
* @return {object} A new AST node.
*/
function createNode(name, type) {
var props = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : null;
var children = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : null;
var node = {
type: type,
name: name
};
if (props) {
node.properties = _objectSpread$1({}, props);
}
if (children) {
node.children = Array.from(children);
}
return node;
}
/**
* Create a new component-typed node.
* @param {string} name Name of the node.
* @param {object[]} props Properties of the node.
* @param {object[]} children Children of the node.
* @return {object} A new component node.
*/
function createComponentNode(name) {
var props = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : null;
var children = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : null;
return createNode(name, COMPONENT, props, children);
}
/**
* Create a new text node.
* @param {string} value Text content on the node.
* @return {object} A new text node.
*/
function createTextNode(value) {
// typeCheckString(value, 'value');
return {
type: TEXTNODE,
value: value
};
}
/**
* Test if a node is a text node.
* @param {object} node The AST node.
* @return {boolean} True if the node is a text node, false otherwise.
*/
function isTextNode(node) {
return node.type === TEXTNODE;
}
/**
* Test if a node is a component node.
* @param {object} node The AST node.
* @return {boolean} True if the node is a component node, false otherwise.
*/
function isComponentNode(node) {
return node.type === COMPONENT;
}
/**
* Test if a node is a variable node, one of 'var', 'derived', or 'data'.
* @param {object} node The AST node.
* @return {boolean} True if the node is a variable node, false otherwise.
*/
function isVariableNode(node) {
return node.type === VAR || node.type === DERIVED || node.type === DATA;
}
/**
* Test if a node is a meta node.
* @param {object} node The AST node.
* @return {boolean} True if the node is a mate node, false otherwise.
*/
function isMetaNode(node) {
return node.type === META;
}
/**
* Get the name of an AST node. If the node is a component, returns
* the component name, otherwise returns the node type.
* @param {object} node The AST node.
* @return {string} The name of the node, or null if not defined.
*/
function getNodeName(node) {
return isComponentNode(node) ? node.name : node.type;
}
/**
* Get the type of an AST node.
* @param {object} node The AST node.
* @return {string} The type of the node, or null if not defined.
*/
function getNodeType(node) {
return node.type || null;
} // -- AST Node Children ----
/**
* Test if an AST node has any child nodes.
* @param {*} node An AST node.
* @returns {boolean} True if the node has children, false otherwise.
*/
function hasChildren(node) {
return node.children ? node.children.length > 0 : false;
}
/**
* Retrieve the children nodes of a parent node.
* This method returns a direct reference to an underlying child
* array. Callers should take care not to modify the returned array.
* @param {object} node The parent node.
* @return {object[]} The children of the node, or an empty array if none.
*/
function getChildren(node) {
return node.children || [];
}
/**
* Sets the child nodes of an AST node.
* @param {object} node The parent node.
* @param {object[]} children The children nodes to set.
* @return {object} The modified AST node.
*/
function setChildren(node, children) {
// typeCheckArray(children, 'children');
node.children = children;
return node;
}
/**
* Append a child node to a parent node.
* @param {object} node The parent AST node.
* @param {object} child The child AST node to append.
* @return {object} A modifed AST node.
*/
function appendChild(node, child) {
return appendChildren(node, [child]);
}
/**
* Append multiple child nodes to a parent node.
* @param {object} node The parent AST node.
* @param {object[]} children The children AST nodes to append.
* @return {object} A modified AST node.
*/
function appendChildren(node, children) {
// typeCheckArray(children, 'children');
var base = node.children || [];
node.children = base.concat(children);
return node;
}
/**
* Prepend a child node to a parent node.
* @param {object} node The parent AST node.
* @param {object} child The child AST node to prepend.
* @return {object} A modifed AST node.
*/
function prependChild(node, child) {
return prependChildren(node, [child]);
}
/**
* Prepend multiple child nodes to a parent node.
* @param {object} node The parent AST node.
* @param {object[]} children The children AST nodes to prepend.
* @return {object} A modified AST node.
*/
function prependChildren(node, children) {
// typeCheckArray(children, 'children');
node.children = children.concat(node.children || []);
return node;
}
/**
* Filter child nodes, retaining only node that match the filter predicate.
* @param {object} node A parent AST node.
* @param {function(object): boolean} predicate Filter function for child nodes.
* @return {object} The modified parent node.
*/
function filterChildren(node, predicate) {
if (hasChildren(node)) {
node.children = node.children.filter(predicate);
}
return node;
}
/**
* Modify child nodes by applying a map function to each. The results of the
* map function become the new child nodes.
* @param {object} node A parent AST node.
* @param {function} mapFunc Map function applied to child nodes.
* @return {object} The modified parent node.
*/
function mapChildren(node, mapFunc) {
if (hasChildren(node)) {
node.children = node.children.map(mapFunc);
}
return node;
} // -- AST Node Properties ----
function hasKeys(object) {
for (var key in object) {
return true;
}
return false;
}
/**
* Tests if an AST node has any defined properties.
* @param {*} node The AST node.
* @returns {boolean} True is the node has properties, false otherwise.
*/
function hasProperties(node) {
return hasKeys(node.properties);
}
/**
* Retrieves the properties object for an AST node.
* @param {object} node The AST node.
* @returns {object} The properties object, or null if none.
*/
function getProperties(node) {
return node.properties || null;
}
/**
* Add a set of properties to an AST node. Any existing
* properties with matching keys will be overwritten.
* @param {object} node The AST node.
* @param {object} properties A properties object. Object keys are
* property names, object values must be property data objects.
* @returns {object} The modified AST node.
*/
function setProperties(node, properties) {
for (var key in properties) {
setProperty(node, key, properties[key]);
}
return node;
}
/**
* Remove all properties from an AST node.
* @param {object} node The AST node.
* @returns {object} The modified AST node.
*/
function clearProperties(node) {
delete node.properties;
return node;
}
/**
* Retrieves an array of property keys for a node.
* @param {object} node The AST node.
* @return {string[]} The property keys, or an empty array if none.
*/
function getPropertyKeys(node) {
return Object.keys(node.properties || {});
}
/**
* Retrieves the property type for a node property.
* @param {object} node The AST node.
* @param {string} key The property key.
* @return {string} The property type, or null if the property is not defined.
*/
function getPropertyType(node, key) {
var prop = getProperty(node, key);
return prop && prop.type || null;
}
/**
* Retrieves the property value for a node property.
* @param {object} node The AST node.
* @param {string} key The property key.
* @return {string} The property value, or null if the property is not defined.
*/
function getPropertyValue(node, key) {
var prop = getProperty(node, key);
return prop && prop.value || null;
}
/**
* Test if a property with the given key is defined on a node.
* @param {object} node The AST node.
* @param {string} key The property key.
* @return {boolean} True if the property is defined, else false.
*/
function hasProperty(node, key) {
return node.properties && node.properties.hasOwnProperty(key) || false;
}
/**
* Retrieves a property of a node given its key.
* @param {object} node The AST node.
* @param {string} key The property key.
* @return {object} The property data, or null if the property does not exist.
*/
function getProperty(node, key) {
return hasProperty(node, key) ? node.properties[key] : null;
}
/**
* Set a property of a node.
* @param {object} node The AST node.
* @param {string} key The property key.
* @param {object} data The property data, should
* be an object with type and value properties.
* @return {object} The modfied AST node.
*/
function setProperty(node, key, data) {
// TODO: type checking of property data?
if (!node.properties) {
node.properties = {};
}
node.properties[key] = data;
return node;
}
/**
* Set a value-typed property of a node.
* @param {object} node The AST node.
* @param {string} key The property key.
* @param {*} value The property value.
* @return {object} The modfied AST node.
*/
function setValueProperty(node, key, value) {
return setProperty(node, key, {
type: VALUE,
value: value
});
}
/**
* Set a variable-typed property of a node.
* @param {object} node The AST node.
* @param {string} key The property key.
* @param {string} value A reactive variable name.
* @return {object} The modfied AST node.
*/
function setVariableProperty(node, key, value) {
return setProperty(node, key, {
type: VARIABLE,
value: value
});
}
/**
* Set an expression-typed property of a node.
* @param {object} node The AST node.
* @param {string} key The property key.
* @param {string} value A JavaScript expression string.
* @return {object} The modfied AST node.
*/
function setExpressionProperty(node, key, value) {
return setProperty(node, key, {
type: EXPRESSION,
value: value
});
}
/**
* Remove a property of a node.
* @param {object} node The AST node.
* @param {string} key The property key.
* @return {object} The modified AST node.
*/
function removeProperty(node, key) {
if (hasProperty(node, key)) {
var _node$properties = node.properties;
_node$properties[key];
var props = _objectWithoutProperties__default["default"](_node$properties, [key].map(_toPropertyKey));
if (hasKeys(props)) {
node.properties = props;
} else {
delete node.properties;
}
}
return node;
} // -- AST Traversal ----
/**
* Perform a preorder depth-first traversal of the AST.
* @param {object} node The AST node at which to begin the traversal.
* @param {function} callack Callback function invoked for each visited node.
*/
function cloneNode(node) {
var clone = _objectSpread$1({}, node);
if (clone.properties) {
clone.properties = _objectSpread$1({}, clone.properties);
}
if (clone.children) {
clone.children = clone.children.map(function (child) {
return cloneNode(child);
});
}
return clone;
}
/**
* Perform a preorder depth-first traversal of the AST.
* @param {object} node The AST node at which to begin the traversal.
* @param {function} callack Callback function invoked for each visited node.
*/
function visitNodes(node, callback) {
callback(node);
getChildren(node).forEach(function (node) {
return visitNodes(node, callback);
});
}
/**
* Retrieve all nodes that match a given predicate function.
* @param {object} node The AST node at which to begin searching.
* Only this node and its descendants are considered.
* @param {function(object): boolean} predicate Filter function to test nodes.
* If the predicate returns true, the node is included in the result.
* @returns {object[]} An array of AST nodes that match the predicate.
*/
function queryNodes(node, predicate) {
var nodes = [];
visitNodes(node, function (n) {
if (predicate(n)) {
nodes.push(n);
}
});
return nodes;
}
/**
* Extract the text from all text nodes under an AST node.
* @param {object} ast The AST node.
* @return {string} The extracted text, concatenated into strings.
*/
function extractText(node) {
var texts = [];
visitNodes(node, function (n) {
if (isTextNode(n)) {
texts.push(n.value);
}
});
return texts.join(' ');
}
/**
* Remove any descendant nodes that match a given predicate function.
* @param {object} node The AST node at which to begin searching.
* Only descendants of this node are considered for removal.
* @param {function(object): boolean} predicate Filter function to test nodes.
* If the predicate returns true, the node is removed from the AST.
* @returns {object} The AST node width descendants removed.
*/
function removeNodes(node, predicate) {
if (hasChildren(node)) {
node.children = node.children.filter(function (child) {
if (predicate(child)) {
return false;
} else {
removeNodes(child, predicate);
return true;
}
});
}
return node;
}
var $schema$1="http://json-schema.org/draft-06/schema#";var title$1="AST Schema V1";var description="Structure of an AST object";var type$1="object";var properties$1={id:{description:"A unique identifier for the current element",type:"integer"},type:{description:"The type category of the element (component/var/derived)",type:"string","enum":["component","var","derived","textnode","data","meta"]},name:{description:"The name of the element",type:"string"},properties:{description:"The properties/attributes of the element",type:"object",patternProperties:{"^\\w+":{description:"Object containing data for the particular property",type:"object",properties:{type:{description:"The evaluation type of the property. Can be value/variable/expression",type:"string","enum":["value","variable","expression"]},value:{description:"Property value",type:["string","number","boolean"]}},additionalProperties:false}}},children:{description:"The children of the element.",type:"array",items:{anyof:[{$ref:"#"},{description:"Structure for a textnode",type:"object",properties:{id:{desceription:"A unique identifier for the current element",id:"integer"},type:{description:"The type category of the element",type:"string","enum":["textnode"]},value:{description:"Text value in the textnode",type:"string"}},required:["type","value"],additionalProperties:false},{description:"Structure for var and derived",type:"object",properties:{id:{desceription:"A unique identifier for the current element",id:"integer"},type:{description:"The type category of the element",type:"string","enum":["var","derived"]},properties:{name:{description:"Name of the variable",type:"object",properties:{type:{type:"string","enum":["value","variable","expression"]},value:{type:"string"}},required:["name","value"],additionalProperties:false},value:{description:"Source for the data",type:"object",properties:{properties:{type:{type:"string","enum":["value","variable","expression"]},value:{type:"string"}}},required:["name","value"],additionalProperties:false}},additionalProperties:false,required:["type","properties"]}},{description:"Structure for data",type:"object",properties:{id:{desceription:"A unique identifier for the current element",id:"integer"},type:{description:"The type category of the element",type:"string","enum":["data"]},properties:{name:{description:"Name of the variable",type:"object",properties:{type:{type:"string","enum":["value","variable","expression"]},value:{type:"string"}},required:["type","value"],additionalProperties:false},source:{description:"Source for the data",type:"object",properties:{properties:{type:{type:"string","enum":["value","variable","expression"]},value:{type:"string"}}},required:["type","value"],additionalProperties:false}},required:["type","properties"]}}]}}};var required=["type"];var schema = {$schema:$schema$1,title:title$1,description:description,type:type$1,properties:properties$1,required:required};
var $schema="http://json-schema.org/draft-06/schema#";var $id="http://json-schema.org/draft-06/schema#";var title="Core schema meta-schema";var definitions={schemaArray:{type:"array",minItems:1,items:{$ref:"#"}},nonNegativeInteger:{type:"integer",minimum:0},nonNegativeIntegerDefault0:{allOf:[{$ref:"#/definitions/nonNegativeInteger"},{"default":0}]},simpleTypes:{"enum":["array","boolean","integer","null","number","object","string"]},stringArray:{type:"array",items:{type:"string"},uniqueItems:true,"default":[]}};var type=["object","boolean"];var properties={$id:{type:"string",format:"uri-reference"},$schema:{type:"string",format:"uri"},$ref:{type:"string",format:"uri-reference"},title:{type:"string"},description:{type:"string"},"default":{},examples:{type:"array",items:{}},multipleOf:{type:"number",exclusiveMinimum:0},maximum:{type:"number"},exclusiveMaximum:{type:"number"},minimum:{type:"number"},exclusiveMinimum:{type:"number"},maxLength:{$ref:"#/definitions/nonNegativeInteger"},minLength:{$ref:"#/definitions/nonNegativeIntegerDefault0"},pattern:{type:"string",format:"regex"},additionalItems:{$ref:"#"},items:{anyOf:[{$ref:"#"},{$ref:"#/definitions/schemaArray"}],"default":{}},maxItems:{$ref:"#/definitions/nonNegativeInteger"},minItems:{$ref:"#/definitions/nonNegativeIntegerDefault0"},uniqueItems:{type:"boolean","default":false},contains:{$ref:"#"},maxProperties:{$ref:"#/definitions/nonNegativeInteger"},minProperties:{$ref:"#/definitions/nonNegativeIntegerDefault0"},required:{$ref:"#/definitions/stringArray"},additionalProperties:{$ref:"#"},definitions:{type:"object",additionalProperties:{$ref:"#"},"default":{}},properties:{type:"object",additionalProperties:{$ref:"#"},"default":{}},patternProperties:{type:"object",additionalProperties:{$ref:"#"},"default":{}},dependencies:{type:"object",additionalProperties:{anyOf:[{$ref:"#"},{$ref:"#/definitions/stringArray"}]}},propertyNames:{$ref:"#"},"const":{},"enum":{type:"array",minItems:1,uniqueItems:true},type:{anyOf:[{$ref:"#/definitions/simpleTypes"},{type:"array",items:{$ref:"#/definitions/simpleTypes"},minItems:1,uniqueItems:true}]},format:{type:"string"},allOf:{$ref:"#/definitions/schemaArray"},anyOf:{$ref:"#/definitions/schemaArray"},oneOf:{$ref:"#/definitions/schemaArray"},not:{$ref:"#"}};var metaSchema = {$schema:$schema,$id:$id,title:title,definitions:definitions,type:type,properties:properties,"default":{}};
function _createSuper(Derived) { var hasNativeReflectConstruct = _isNativeReflectConstruct(); return function _createSuperInternal() { var Super = _getPrototypeOf__default["default"](Derived), result; if (hasNativeReflectConstruct) { var NewTarget = _getPrototypeOf__default["default"](this).constructor; result = Reflect.construct(Super, arguments, NewTarget); } else { result = Super.apply(this, arguments); } return _possibleConstructorReturn__default["default"](this, result); }; }
function _isNativeReflectConstruct() { if (typeof Reflect === "undefined" || !Reflect.construct) return false; if (Reflect.construct.sham) return false; if (typeof Proxy === "function") return true; try { Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); return true; } catch (e) { return false; } }
var ajv = new Ajv__default["default"]();
ajv.addMetaSchema(metaSchema);
var astValidator;
var propValidator;
var MalformedASTError = /*#__PURE__*/function (_Error) {
_inherits__default["default"](MalformedASTError, _Error);
var _super = _createSuper(MalformedASTError);
function MalformedASTError(msg, errors) {
var _this;
_classCallCheck__default["default"](this, MalformedASTError);
_this = _super.call(this, msg);
_this.name = _this.constructor.name;
_this.message = msg;
_this.stack = new Error(msg).stack;
return _this;
}
return _createClass__default["default"](MalformedASTError);
}( /*#__PURE__*/_wrapNativeSuper__default["default"](Error));
/**
* Validates if an AST node conforms to the JSON schema.
* @param {object} node The AST node.
* @throws Error if AST validation fails.
*/
function validateNode(ast) {
if (!astValidator) {
astValidator = ajv.compile(schema);
}
if (!astValidator(ast)) {
throw new MalformedASTError('AST node does not match schema: ' + astValidator.errors[0].message);
}
}
/**
* Validates if AST node properties conform to the JSON schema.
* @param {object} properties An AST node properties object.
* @throws Error if AST validation fails.
*/
function validateProperties(properties) {
if (!propValidator) {
propValidator = ajv.compile(schema.properties.properties);
}
if (!propValidator(properties)) {
throw new MalformedASTError('AST properties do not match schema: ' + propValidator.errors[0].message);
}
}
/*
THIS FILE CONTAINS THE CONVERTER FUNCTIONS FOR THE TWO DIFFERENT TYPES OF AST STRUCTURE.
*/
/**
* This function converts the JSON structured AST (ASTV2) to the array structured
* AST (OLD AST)
* @param {*} jsonAst
* @return Array structred AST
*/
var convertV2ToV1 = function convertV2ToV1(jsonAst) {
var arrayAst = [];
if (jsonAst.children) {
jsonAst.children.forEach(function (element) {
arrayAst.push(convertHelper(element));
});
}
return arrayAst;
};
/**
* Helper function for convert
* @param {*} jsonElement
* @return array representation of the corresponding jsonElement
*/
function convertHelper(jsonElement) {
var elementArray = [];
if (jsonElement.type === 'textnode') {
return jsonElement.value;
} else if (jsonElement.type === 'var' || jsonElement.type === 'derived') {
elementArray = [jsonElement.type];
elementArray.push([['name', ['value', jsonElement.name]], ['value', ['value', jsonElement.value]]]);
elementArray.push([]);
} else if (jsonElement.type === 'data') {
elementArray = ['data'];
elementArray.push([['name', ['value', jsonElement.name]], ['source', ['value', jsonElement.source]], ['async', ['value', jsonElement.async]], ['initialValue', ['expression', jsonElement.initialValue]]]);
elementArray.push([]);
} else {
elementArray.push(jsonElement.name);
var propertiesArray = [];
if ('properties' in jsonElement) {
Object.keys(jsonElement.properties).forEach(function (key) {
var propertyArray = [key];
propertyArray.push([jsonElement.properties[key].type, jsonElement.properties[key].value]);
propertiesArray.push(propertyArray);
});
}
elementArray.push(propertiesArray);
if ('children' in jsonElement) {
var childArray = [];
jsonElement.children.forEach(function (children) {
childArray.push(convertHelper(children));
});
elementArray.push(childArray);
}
}
return elementArray;
}
/**
* This function converts the array structred AST (OLD AST) to the new
* JSON structured ast(ASTV2)
* @param {*} arrayAst
* @return Json structred ast correspoding to the arrayAst.
*/
var convertV1ToV2 = function convertV1ToV2(arrayAst, injectIds) {
var _id = 0;
var id = injectIds ? function () {
return _id++;
} : null;
var jsonAst = new Object();
if (id) jsonAst.id = id();
jsonAst.type = 'component';
jsonAst.name = 'div';
jsonAst.children = arrayAst.map(function (element) {
return inverseConvertHelper(element, id);
});
return jsonAst;
};
/**
* Helper function for inverseConvert
* @param {*} arrayElement
* @return JSON representation of the corresponding arrayElement
*/
function inverseConvertHelper(arrayElement, id) {
var elementJson = new Object();
if (id) elementJson.id = id();
if (typeof arrayElement === 'string') {
elementJson.type = 'textnode';
elementJson.value = arrayElement;
} else if (['var', 'derived', 'data', 'meta'].indexOf(arrayElement[0]) > -1) {
elementJson.type = arrayElement[0];
elementJson.properties = {};
arrayElement[1].forEach(function (property) {
elementJson.properties[property[0]] = {
type: property[1][0],
value: property[1][1]
};
});
} else {
elementJson.type = 'component';
elementJson.name = arrayElement[0];
if (arrayElement[1].length !== 0) {
elementJson.properties = {};
arrayElement[1].forEach(function (property) {
elementJson.properties[property[0]] = {
type: property[1][0],
value: property[1][1]
};
});
}
if (arrayElement[2]) {
elementJson.children = arrayElement[2].map(function (element) {
return inverseConvertHelper(element, id);
});
}
}
return elementJson;
}
function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); enumerableOnly && (symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; })), keys.push.apply(keys, symbols); } return keys; }
function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = null != arguments[i] ? arguments[i] : {}; i % 2 ? ownKeys(Object(source), !0).forEach(function (key) { _defineProperty__default["default"](target, key, source[key]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)) : ownKeys(Object(source)).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } return target; }
function _createForOfIteratorHelper(o, allowArrayLike) { var it = typeof Symbol !== "undefined" && o[Symbol.iterator] || o["@@iterator"]; if (!it) { if (Array.isArray(o) || (it = _unsupportedIterableToArray(o)) || allowArrayLike && o && typeof o.length === "number") { if (it) o = it; var i = 0; var F = function F() {}; return { s: F, n: function n() { if (i >= o.length) return { done: true }; return { done: false, value: o[i++] }; }, e: function e(_e) { throw _e; }, f: F }; } throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); } var normalCompletion = true, didErr = false, err; return { s: function s() { it = it.call(o); }, n: function n() { var step = it.next(); normalCompletion = step.done; return step; }, e: function e(_e2) { didErr = true; err = _e2; }, f: function f() { try { if (!normalCompletion && it["return"] != null) it["return"](); } finally { if (didErr) throw err; } } }; }
function _unsupportedIterableToArray(o, minLen) { if (!o) return; if (typeof o === "string") return _arrayLikeToArray(o, minLen); var n = Object.prototype.toString.call(o).slice(8, -1); if (n === "Object" && o.constructor) n = o.constructor.name; if (n === "Map" || n === "Set") return Array.from(o); if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray(o, minLen); }
function _arrayLikeToArray(arr, len) { if (len == null || len > arr.length) len = arr.length; for (var i = 0, arr2 = new Array(len); i < len; i++) { arr2[i] = arr[i]; } return arr2; }
/**
* Convert an AST to valid Idyll markup.
* @param {object} node The AST node.
* @return {string} The markup string.
*/
function toMarkup(node) {
var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {
insertFullWidth: false
};
var markup = childrenToMarkup(node, 0, node.name === 'p' ? ' ' : '\n', options.insertFullWidth || false).trim();
var cleanedMarkup = markup.replace(/([\]\*\_]) ([,\.\!\?\:\[])/g, '$1$2');
return cleanedMarkup;
}
function childrenToMarkup(node, depth) {
var separator = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : '\n';
var insertFullWidth = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : false;
var markup = '';
var _iterator = _createForOfIteratorHelper(getChildren(node)),
_step;
try {
for (_iterator.s(); !(_step = _iterator.n()).done;) {
var child = _step.value;
markup += separator + nodeToMarkup(child, depth, separator, insertFullWidth);
}
} catch (err) {
_iterator.e(err);
} finally {
_iterator.f();
}
return markup.replace(/\n\n+/g, '\n\n');
}
function nodeToMarkup(node, depth) {
var separator = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : '\n';
var insertFullWidth = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : false;
var name = node.name && node.name.toLowerCase() || null;
if (name === 'idylleditordroptarget') {
return '';
}
var markupNodes = ['strong', 'em', 'i', 'b', 'code', 'h1', 'h2', 'h3', 'h4', 'h5', 'a']; // normalize component names
if (name && !htmlTags__default["default"].includes(name)) {
node.name = node.name.split('-').map(function (s) {
return s.charAt(0).toUpperCase() + s.slice(1);
}).join('');
name = node.name.toLowerCase();
}
switch (node.type) {
case 'textnode':
return "".concat(' '.repeat(depth)).concat(node.value.trim());
case 'component':
if (name === 'textcontainer') {
return "\n".concat(childrenToMarkup(node, depth, '\n', false));
} else if (name === 'p' && depth < 1) {
return "\n".concat(childrenToMarkup(node, depth, '\n', false).trim(), "\n");
} else if (markupNodes.includes(name)) {
switch (name) {
case 'strong':
case 'b':
return "**".concat(childrenToMarkup(node, 0, ' ', false).trim(), "**");
case 'em':
case 'i':
return "*".concat(childrenToMarkup(node, 0, ' ', false).trim(), "*");
case 'code':
return "`".concat(childrenToMarkup(node, 0, ' ', false).trim(), "`");
case 'h1':
case 'h2':
case 'h3':
case 'h4':
case 'h5':
if (node.children && node.children.length === 1 && node.children[0].type === 'textnode') {
return "".concat('#'.repeat(+node.name[1]), " ").concat(childrenToMarkup(node, 0, ' ', false).trim());
}
}
}
if (name === 'pre' && node.children && node.children.length === 1 && node.children[0].name && node.children[0].name.toLowerCase() === 'code') {
return "\n```\n".concat(childrenToMarkup(node.children[0], 0, ' ', false).trim(), "\n```\n ");
} else if (name === 'pre' && node.children && node.children.length === 1 && node.children[0].type === 'textnode') {
return "\n```\n".concat(childrenToMarkup(node, 0, ' ', false).trim(), "\n```");
}
var propString = propertiesToString(node, depth, insertFullWidth);
if (hasChildren(node)) {
if (name === 'a') {
return "".concat(' '.repeat(depth), "[").concat(node.name).concat(propString ? "".concat(propString) : '', "]").concat(childrenToMarkup(node, depth + 1, ' ', false).trim(), "[/").concat(node.name, "]");
}
return "".concat(' '.repeat(depth), "[").concat(node.name).concat(propString ? "".concat(propString) : '', "]").concat(childrenToMarkup(node, depth + 1, separator, false), "\n").concat(' '.repeat(depth), "[/").concat(node.name, "]");
}
return "".concat(' '.repeat(depth), "[").concat(node.name).concat(propString ? "".concat(propString) : '', " /]");
case 'var':
case 'derived':
case 'data':
case 'meta':
return "".concat(' '.repeat(depth), "[").concat(node.type).concat(propertiesToString(node, depth, insertFullWidth), " /]");
}
}
function propertiesToString(node, depth, insertFullWidth) {
var props = _objectSpread({}, node.properties);
if (insertFullWidth && isComponentNode(node) && node.name.toLowerCase() !== 'textcontainer') {
props.fullWidth = {
type: 'value',
value: true
};
}
var flatString = Object.keys(props || {}).reduce(function (memo, key) {
return memo + " ".concat(key, ":").concat(propertyToString(props[key]));
}, '');
if (flatString.length < 60) {
return flatString;
}
return Object.keys(props || {}).reduce(function (memo, key) {
return memo + "\n".concat(' '.repeat(depth + 1)).concat(key, ":").concat(propertyToString(props[key]));
}, '');
}
function propertyToString(property) {
switch (property.type) {
case VALUE:
return JSON.stringify(property.value);
case EXPRESSION:
return "`".concat(property.value, "`");
case VARIABLE:
return property.value;
}
}
exports.COMPONENT = COMPONENT;
exports.DATA = DATA;
exports.DERIVED = DERIVED;
exports.EXPRESSION = EXPRESSION;
exports.META = META;
exports.TEXTNODE = TEXTNODE;
exports.VALUE = VALUE;
exports.VAR = VAR;
exports.VARIABLE = VARIABLE;
exports.appendChild = appendChild;
exports.appendChildren = appendChildren;
exports.clearProperties = clearProperties;
exports.cloneNode = cloneNode;
exports.convertV1ToV2 = convertV1ToV2;
exports.convertV2ToV1 = convertV2ToV1;
exports.createComponentNode = createComponentNode;
exports.createNode = createNode;
exports.createTextNode = createTextNode;
exports.extractText = extractText;
exports.filterChildren = filterChildren;
exports.getChildren = getChildren;
exports.getNodeName = getNodeName;
exports.getNodeType = getNodeType;
exports.getProperties = getProperties;
exports.getProperty = getProperty;
exports.getPropertyKeys = getPropertyKeys;
exports.getPropertyType = getPropertyType;
exports.getPropertyValue = getPropertyValue;
exports.hasChildren = hasChildren;
exports.hasProperties = hasProperties;
exports.hasProperty = hasProperty;
exports.isComponentNode = isComponentNode;
exports.isMetaNode = isMetaNode;
exports.isTextNode = isTextNode;
exports.isVariableNode = isVariableNode;
exports.mapChildren = mapChildren;
exports.prependChild = prependChild;
exports.prependChildren = prependChildren;
exports.queryNodes = queryNodes;
exports.removeNodes = removeNodes;
exports.removeProperty = removeProperty;
exports.setChildren = setChildren;
exports.setExpressionProperty = setExpressionProperty;
exports.setProperties = setProperties;
exports.setProperty = setProperty;
exports.setValueProperty = setValueProperty;
exports.setVariableProperty = setVariableProperty;
exports.toMarkup = toMarkup;
exports.validateNode = validateNode;
exports.validateProperties = validateProperties;
exports.visitNodes = visitNodes;
//# sourceMappingURL=index.js.map