New walk_tags to replace old bbcode_match func

This commit is contained in:
斟酌 鵬兄 2022-04-09 20:42:54 +08:00
parent 96c0899240
commit cf6fd2e35e
2 changed files with 138 additions and 0 deletions

View File

@ -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
};

114
string.js
View File

@ -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 "</abcd>"
if( closeTag )
{
// Hits "<abcd...>...</abcd>"
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 "<abcd>...</efgh>"
else
{
throw new Error( `Syntax error: Unexpected closing ${_OP}${t}> after opened ${_OP}${tokenStack.curr().name}${_ED}` );
}
}
// Hits "<abcd>"
else
{
tokenStack.add( _newStackItem( t ) );
_fd = tokenStack.curr().fd;
_fineHandlers.TagOpen && _fineHandlers.TagOpen( ctx );
continue;
}
}
else
{
// Hits "<abc#" where _a is "#"
// Consume everything until we hit closing ">" 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 "<abcd#...<"
if( _a === _OP )
{
// Write "<abcd#..." into _fd and starts over
// < : _OP
// abcd : tokenStack.pop().name
// #... : t
_fd( _OP + tokenStack.pop().name + t ); i --;
continue;
}
// Hits "<abcd#...>"
else
{
// Write #... into abcd's attrs
tokenStack.curr().attrs = t;
_fd = tokenStack.curr().fd;
continue;
}
}
}
else
{
_fd( c );
}
}
return strOut;
}
}