sbis3-node-ws
Version:
Модуль позволяет использовать ядро интерфейсного фреймворка sbis3-ws(`core.js`) и модуль работы с данными (`Source.js`) в приложении на nodejs.
420 lines • 15.8 kB
JavaScript
/**
* Parsing step
* Traversing/parsing AST-html tree
*/
define('js!Core/tmpl/js/traverse',
[
'js!Core/tmpl/js/jison/htmlparser',
'js!Core/tmpl/js/helpers/utils',
'js!Core/tmpl/js/helpers/skipVars',
'js!Core/tmpl/js/helpers/State',
'js!Core/tmpl/js/astModules/module',
'js!Core/tmpl/js/helpers/entityHelpers',
'js!Core/tmpl/js/astModules/includeAMD',
'js!Core/tmpl/js/astModules/template',
'js!Core/tmpl/js/astModules/partial',
'js!Core/tmpl/js/astModules/if',
'js!Core/tmpl/js/astModules/for',
'js!Core/tmpl/js/helpers/errorHandling'
], function traverseLoader(htmlparser, utils, skipVars, State, moduleC, entityHelpers, inc, tmp, par, ifM, fr, errorHandling) {
'use strict';
var traverse = {
/**
* Modules to traverse on parse step
*/
_modules: {
'ws:include': inc,
'ws:template': tmp,
'ws:partial': par,
'ws:for': fr
},
/**
* Attribute module to traverse on parse step
*/
_attributeModules: {
'for': fr
},
/**
* Regular expression for finding variables/expression inside of AST
*/
_regex: {
forVariables: /\{\{ ?(.*?) ?\}\}/g
},
/**
* Safe replacing
*/
safeReplaceCaseReg: /\r|\n|\t|\/\*[\s\S]*?\*\//g,
/**
* Safe placeholder
*/
safeReplaceCasePlace: "",
/**
* Include promises stack
* @type {Object}
*/
includeStack: {},
/**
* Parsing html string to the directive state
* @param {String} tmpl string html template
* @param {Function} handler function for handling parsing result
* @return {Array} html AST
*/
parse: function parse(tmpl, handler) {
var
handlerObject = new htmlparser.DefaultHandler(handler || this.defaultHandler, {
ignoreWhitespace: true
}),
parser = new htmlparser.Parser(handlerObject);
parser.parseComplete(tmpl);
return handlerObject.dom;
},
/**
* Attribute traverse in order to find variables
* @param {Array} array of attributes
* @return {Array} array of attributes with variables
*/
_traverseTagAttributes: function traverseTagAttributes(attribs) {
var dataAttributes = utils.clone(attribs);
return utils.eachObject(dataAttributes, function traverseTagAttributesEach(attrib) {
return this._traverseText({
data: attrib
});
}.bind(this));
},
/**
* Removing unnecessary stuff from strings
* @param {String} string data string
* @return {String} clean data string
*/
_replaceAllUncertainStuff: function replaceAllUncertainStuff(string) {
return string.replace(this.safeReplaceCaseReg, this.safeReplaceCasePlace);
},
/**
* Searching for vars in string
* @param {Array} arrOfVars array of variables and text
* @return {Array} array of variables
*/
_searchForVars: function searchForVars(arrOfVars) {
return utils.mapForLoop(arrOfVars, function searchForVarsLoop(value) {
return value.split(this._regex.forVariables).join('');
}.bind(this));
},
/**
* Replacing and creating statements for variables and text chunks
* @param {Array} data array of incoming data
* @param {Array} arrOfVars array with variables
* @return {Array} array with objects
*/
_replaceAndCreateStatements: function replaceAndCreateStatements(data, arrOfVars) {
var array = [], i, emptyString = "";
for (i = 0; i < data.length; i++) {
if (data[i] !== emptyString) {
array.push(skipVars.checkStatementForInners(data[i], arrOfVars));
}
}
return array;
},
_createDataObjectWorkWithProperty: function createDataObjectWorkWithProperty(data, arrOfVarsClean) {
if (arrOfVarsClean) {
return this._replaceAndCreateStatements(data, arrOfVarsClean);
}
return entityHelpers.createDataText(data[0]);
},
/**
* Looking for variables in string data object
* @param {Object} strObjectData
* @param {Array} arrOfVarsClean Array of variables in data object
* @return {Object}
*/
_createDataObject: function createDataObject(strObjectData, arrOfVarsClean) {
strObjectData.data = this._createDataObjectWorkWithProperty(strObjectData.data, arrOfVarsClean);
return strObjectData;
},
/**
* Preparing data-like string for structured tree
* @param {Object} str incoming data string
* @return {Object} data object { data: { type: "text", value: 'wadawd' } }
*/
_replaceMatch: function replaceMatch(strObjectData) {
var
resString = this._replaceAllUncertainStuff(strObjectData.data),
arrOfVars = resString.match(this._regex.forVariables),
arrOfVarsClean;
if (arrOfVars) {
arrOfVarsClean = this._searchForVars(arrOfVars);
}
strObjectData.data = resString.split(this._regex.forVariables);
return this._createDataObject(strObjectData, arrOfVarsClean);
},
/**
* Looking for variables in strings
* @param {String} statement string statement
* @return {Object} data object { data: { type: "text", value: 'wadawd' } }
*/
_lookForStatements: function lookForStatements(statement) {
if (statement) {
return this._replaceMatch(statement);
}
},
_handlingTag: function handlingTag(name) {
if (this._modules[name]) {
return this._traverseModule;
}
if (entityHelpers.isTagRequirable(name)) {
return this._traverseOptionModule;
}
return this._traverseTag;
},
/**
* Resolving method to handle tree childs
* @param {Object} entity tag, text or module
* @return {Function} traverse method to use
*/
_whatMethodShouldYouUse: function whatMethodShouldYouUse(entity) {
if (entityHelpers.isTag(entity.type)) {
return this._handlingTag(entity.name)
}
if (entityHelpers.isText(entity.type)) {
return this._traverseText;
}
},
/**
* Perform action on main data array
* @param {Array} modAST AST array
* @param {Object|Array} traverseObject object or array of objects with tag or text
* @return {Array} AST array
*/
actionOnMainArray: function actionOnMainArray(modAST, traverseObject) {
if (traverseObject !== undefined && traverseObject.length > 0) {
for (var i = 0; i < traverseObject.length; i++) {
modAST.push(traverseObject[i]);
}
}
traverseObject = null;
return modAST;
},
/**
* Collecting states from traversing tree
* @param {Function} traverseMethod traverse function for entity
* @param {Object} value Tag, text or module
* @return {Object} State promise
*/
_collect: function collect(traverseMethod, value) {
return traverseMethod.call(this, value);
},
/**
* Traversing ast
* @param {Array} ast AST array
* @return {Array} array of State promises
*/
traversingAST: function traversingAST(ast, prefix) {
var traverseMethod,
psArray = [],
keyIndex = 0,
collect;
for (var i = 0; i < ast.length; i++) {
traverseMethod = this._whatMethodShouldYouUse(ast[i]);
if (traverseMethod) {
if (utils.checkForKeys(ast[i])) {
ast[i].key = keyIndex++;
ast[i].prefix = prefix;
}
collect = this._collect(traverseMethod, ast[i]);
if (collect !== undefined) {
psArray.push(collect);
}
}
}
return State.every(psArray);
},
/**
* Starting point
* @param {Array} ast [description]
* @return {Object} State promise
*/
traverse: function traverse(ast, resolver, config) {
if (resolver) {
this.resolver = resolver;
if (config) {
this.filename = config.filename;
}
}
return this.traversingAST(ast).when(
function resulting(data) {
return this.actionOnMainArray([], data);
}.bind(this),
function broken(reason) {
errorHandling(reason, this.filename);
}
);
},
/**
* Generating tag and tag childs
* @param {Object} tag tag
* @param {Array} inner children
* @return {Object} Tag
*/
_generatorFunctionForTags: function generatorFunctionForTags(tag, inner) {
tag.children = this.actionOnMainArray([], inner);
return tag;
},
/**
* Traversing tag with children
* @param {Object} tag
* @return {Object} State promise
*/
traverseTagWithChildren: function traverseTagWithChildren(tag) {
return this.traversingAST(tag.children, tag.prefix).when(
function traverseTagSuccess(ast) {
return this._generatorFunctionForTags(tag, ast);
}.bind(this),
function brokenTagTraversing(reason) {
errorHandling(reason, this.filename);
}
);
},
/**
* Traverse manageable attributes from _attributeModules
* @param attribs
* @returns {Array}
*/
_traverseManageableAttributes: function traverseManageableAttributes(attribs) {
var constructArray = [], attrib;
for (attrib in attribs) {
if (this._attributeModules.hasOwnProperty(attrib) && attribs[attrib]) {
constructArray.push({ module: attrib, value: attribs[attrib] });
}
}
return constructArray;
},
/**
* Apply module function on tag with manageable attributes
* @param tag
* @returns {*}
*/
_useManageableAttributes: function useManageableAttributes(tag) {
var constructArray = this._traverseManageableAttributes(tag.attribs);
if (!!constructArray.length) {
return entityHelpers.loadModuleFunction.call(this, entityHelpers.attributeMatcherByName.call(this, constructArray.shift().module), tag);
}
return this._generateTag(tag);
},
/**
* Checking tag for manageable attributes
* @param tag
* @returns {*}
*/
_checkForManageableAttributes: function checkForManageableAttributes(tag) {
if (tag.attribs) {
return this._useManageableAttributes(tag);
}
return this._generateTag(tag);
},
/**
* Generating tag object
* @param tag
* @returns {*}
*/
_generateTag: function generateTag(tag) {
var state,
attribs = this._traverseTagAttributes(tag.attribs),
takeTag = this._acceptTag(tag, attribs);
if (takeTag.children && takeTag.children.length > 0) {
return this.traverseTagWithChildren(takeTag);
}
state = State.make();
state.keep(this._generatorFunctionForTags(takeTag));
return state.promise;
},
/**
* Main function for tag traversing
* @param {Object} tag
* @return {Object} State promise
*/
_traverseTag: function traverseTag(tag) {
return this._checkForManageableAttributes(tag);
},
/**
* Traverse requirable tag
* @param tag
* @returns {Array}
*/
_traverseOptionModule: function traverseOptionModule(tag) {
return entityHelpers.loadModuleFunction.call(this, moduleC.parse, tag)
},
/**
* Main function for finding traverse method for module
* @param {Object} tag
* @return {Array} Module function
*/
_traverseModule: function traverseModule(tag) {
var tagModule = entityHelpers.parserMatcher.call(this, tag);
return entityHelpers.loadModuleFunction.call(this, tagModule, tag);
},
/**
* Text node traversing
* @param {Object} text
* @return {Object} promise or text
*/
_traverseText: function traverseText(text) {
var text = utils.clone(text),
state = State.make();
if (text.hasOwnProperty('type')) {
text.raw = this._replaceAllUncertainStuff(text.raw);
state.keep(this._lookForStatements(text));
return state.promise;
}
return this._lookForStatements(text);
},
/**
* Creating tag
* @param {String} name
* @param {Array|Object} data
* @param {String} raw
* @param {Object} attribs
* @param {Array} children
* @return {Object}
*/
_createTag: function createTag(tag) {
return {
name: tag.name,
data: tag.data,
raw: tag.raw,
key: tag.key,
attribs: tag.attribs,
children: tag.children,
selfclosing: tag.selfclosing,
type: "tag"
};
},
/**
* Accepting tag to the AST
* @param tag
* @param attribs
* @returns {Object}
*/
_acceptTag: function acceptTag(tag, attribs) {
return this._createTag({
name: tag.name,
data: tag.data,
raw: tag.raw,
key: tag.key,
attribs: attribs,
children: tag.children,
selfclosing: !!tag.selfclosing
});
},
/**
* Default handler for parsing
* @param {Error} error
* @param {Array} dom
* @return
*/
defaultHandler: function defaultHandler(error, dom) {
if (error) {
errorHandling(error, this.filename);
}
}
};
return traverse;
});