diff --git a/object.js b/object.js index ca68d5a..226821a 100644 --- a/object.js +++ b/object.js @@ -61,7 +61,31 @@ var referenceObj = function() return refd; }; +var LStack = function() { + this._first = null; +}; + +LStack.prototype.add = function( obj ) +{ + var p = this._first; + this._first = { "o": obj, "n": p }; +}; + +LStack.prototype.pop = function() +{ + var g = this._first; + this._first = g.n; + return g.o; +}; + +LStack.prototype.curr = function() { + return this._first.o; +}; + +LStack.prototype.empty = function() { return !this._first; } + module.exports = { clone: cloneObj , refObj: referenceObj + , LStack: LStack }; diff --git a/string.js b/string.js index 07b0e73..c33e77e 100644 --- a/string.js +++ b/string.js @@ -1,3 +1,10 @@ +var obju = require( "./object.js" ); +var _newStackItem = function( t ) +{ + var o = { "name": t, "attrs": "", "cont": "" }; + o[ "fd" ] = ( x ) => o.cont += x; + return o; +}; module.exports = { encodeHtml: function ( str, br ) { @@ -19,4 +26,111 @@ module.exports = { return "http://" + str; } + , walk_tags: function( str, handler, _OP, _ED, _fineHandlers ) + { + _fineHandlers ||= {}; + + var l = str && str.length; + var strOut = ""; + + var tokenStack = new (obju.LStack)(); + + var _fd_strOut = ( x ) => strOut += x; + var _fd = _fd_strOut; + + var exitCurrentTag = () => { + tokenStack.pop(); + _fd = tokenStack.empty() ? _fd_strOut : tokenStack.curr().fd; + }; + + var ctx = { + "exitCurrentTag": exitCurrentTag + , "stack": tokenStack + }; + + for( let i = 0; i < l; i ++ ) + { + let c = str[i]; + let t, _a, _n; + if( c === _OP ) + { + t = str[ ++i ]; + let closeTag = ( t === "/" ); + + for( + _a = str[ ++i ], _n = _a.charCodeAt(0); + // check alpha numeric + ( 65 <= _n && _n <= 90 ) || ( 97 <= _n && _n <= 122 ) || ( 48 <= _n && _n <= 57 ); + i ++, _a = str[i], _n = _a.charCodeAt(0) + ) t += _a; + + if( _a === _ED ) + { + // Hits "" + if( closeTag ) + { + // Hits "..." + if( t.substr( 1 ) === tokenStack.curr().name ) + { + let st = tokenStack.pop(); + _fd = tokenStack.empty() ? _fd_strOut : tokenStack.curr().fd; + _fd( handler( st.name, st.attrs, st.cont ) ); + continue; + } + // Hits "..." + else + { + throw new Error( `Syntax error: Unexpected closing ${_OP}${t}> after opened ${_OP}${tokenStack.curr().name}${_ED}` ); + } + } + // Hits "" + else + { + tokenStack.add( _newStackItem( t ) ); + _fd = tokenStack.curr().fd; + + _fineHandlers.TagOpen && _fineHandlers.TagOpen( ctx ); + continue; + } + } + else + { + // Hits "" or opening "<" + tokenStack.add( _newStackItem( t ) ); + t = _a; + for( + _a = str[ ++i ]; + !( _a.startsWith( _OP ) || _a.startsWith( _ED ) ); + i ++, _a = str[i] + ) t += _a; + + // Hits "" + else + { + // Write #... into abcd's attrs + tokenStack.curr().attrs = t; + _fd = tokenStack.curr().fd; + continue; + } + } + } + else + { + _fd( c ); + } + } + + return strOut; + } }