forked from Mithgol/node-abstract-syntax-tree
-
Notifications
You must be signed in to change notification settings - Fork 0
/
astree.js
92 lines (82 loc) · 3.09 KB
/
astree.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
var ASTree = function(){
if (!(this instanceof ASTree)) return new ASTree();
this.splitters = [];
this.renderers = [];
this.renderAST = this.ASTRenderer.bind(this);
};
ASTree.prototype.ASTRenderer = function(AST){
var sourceArray = AST;
var _this = this;
if( !Array.isArray(sourceArray) ) sourceArray = [ sourceArray ];
return sourceArray.map(function(sourceItem){
if( typeof sourceItem === 'string' ) return sourceItem;
if( typeof sourceItem.type === 'undefined' ){
return sourceItem.toString();
}
var foundRenderer = _this.renderers.find(function(someRenderer){
return someRenderer.supportedNodeTypes.indexOf(
sourceItem.type
) > -1;
});
if( typeof foundRenderer === 'undefined' ) return sourceItem.toString();
return foundRenderer.renderer( sourceItem, _this.renderAST );
}).join('');
};
ASTree.prototype.render = function(initialString){
var prevArray, nextArray;
prevArray = [initialString];
this.splitters.forEach(function(nextSplitter){
nextArray = [];
prevArray.forEach(function(targetElement){
var supportedNode = nextSplitter.supportedNodeTypes.find(
supportedNodeType => targetElement.type === supportedNodeType.type
);
if( typeof supportedNode === 'undefined' ){
// default behaviour: apply the splitter to the target element
nextArray = nextArray.concat(
nextSplitter.splitter(targetElement)
);
return;
}
// changed behaviour: apply the splitter to the targeted properties
supportedNode.props.forEach(function(targetedPropName){
if( Array.isArray(targetElement[targetedPropName]) ){
var nextPropValue = [];
targetElement[targetedPropName].forEach(function(propItem){
nextPropValue = nextPropValue.concat(
nextSplitter.splitter(propItem)
);
});
targetElement[targetedPropName] = nextPropValue;
} else if(
typeof targetElement[targetedPropName] !== 'undefined'
){
targetElement[targetedPropName] = nextSplitter.splitter(
targetElement[targetedPropName]
);
}
});
nextArray = nextArray.concat(targetElement);
});
prevArray = nextArray;
});
prevArray = null;
return this.renderAST( nextArray );
};
ASTree.prototype.defineSplitter = function(splitter, supportedNodeTypes){
if( typeof supportedNodeTypes === 'undefined' ) supportedNodeTypes = [];
this.splitters.push({
'splitter': splitter,
'supportedNodeTypes': supportedNodeTypes
});
};
ASTree.prototype.defineRenderer = function(supportedNodeTypes, renderer){
if( !Array.isArray(supportedNodeTypes) || supportedNodeTypes.length < 1 ){
throw new Error('Wrong `supportedNodeTypes` in `.defineRenderer`.');
}
this.renderers.push({
'renderer': renderer,
'supportedNodeTypes': supportedNodeTypes
});
};
module.exports = ASTree;