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 )
{
str = ( str + "" ).replace(/&/g, "&")
.replace(//g, ">")
.replace(/"/g, """)
.replace(/'/g, "'")
;
if( br ) str = str.replace( /\n/g, "
" );
return str;
}
, http_str: function( str )
{
if( str.match( "^https?://" ) )
{
return str;
}
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 )
{
let closeTag = ( str[ i + 1 ] === "/" );
if( closeTag )
{
t = str[ ++i ];
}
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( t === "" || t === "/" )
{
// Hits "<#" where # is not a valid tag name
_fd( t + _a );
continue;
}
if( _a === _ED )
{
// Hits ""
if( closeTag )
{
// Hits "..." with no corresponding open tag
if( tokenStack.empty() )
{
if( _fineHandlers.UnmatchedCloseTag )
{
_fineHandlers.UnmatchedCloseTag( ctx, t.substr( 1 ) );
}
else
{
throw new Error( `Syntax Error: Unexpected closing ${_OP}${t}${_ED}` );
}
}
// Hits "..."
else 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
{
if( _fineHandlers.UnmatchedCloseTag )
{
_fineHandlers.UnmatchedCloseTag( ctx, t.substr( 1 ) );
}
else
{
throw new Error( `Syntax error: Unexpected closing ${_OP}${t}${_ED} 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;
_fineHandlers.TagOpen && _fineHandlers.TagOpen( ctx );
continue;
}
}
}
else
{
_fd( c );
}
}
return strOut;
}
}