mirror of
https://github.com/flynx/pWiki.git
synced 2026-08-25 00:36:41 +00:00
correct nested filter handling....
Signed-off-by: Alex A. Naanou <alex.nanou@gmail.com>
This commit is contained in:
parent
8ad2f12fc8
commit
b1c1c4024f
@ -273,7 +273,8 @@ module.BaseParser = {
|
|||||||
return f in (that.filters ?? {})})
|
return f in (that.filters ?? {})})
|
||||||
var handle = function(str){
|
var handle = function(str){
|
||||||
// skip non-basic data...
|
// skip non-basic data...
|
||||||
if(typeof(str) == 'object'){
|
if(typeof(str) == 'object'
|
||||||
|
|| typeof(str) == 'function'){
|
||||||
return str }
|
return str }
|
||||||
return filters
|
return filters
|
||||||
.reduce(function(res, filter){
|
.reduce(function(res, filter){
|
||||||
@ -686,6 +687,7 @@ module.BaseParser = {
|
|||||||
// sync...
|
// sync...
|
||||||
} else {
|
} else {
|
||||||
elem.value = res }
|
elem.value = res }
|
||||||
|
|
||||||
elems.push(elem) }
|
elems.push(elem) }
|
||||||
|
|
||||||
// cleanup...
|
// cleanup...
|
||||||
@ -797,18 +799,15 @@ module.BaseParser = {
|
|||||||
// Merge and apply global filters (stage III)...
|
// Merge and apply global filters (stage III)...
|
||||||
//
|
//
|
||||||
// - ensure the ast is fully resolved
|
// - ensure the ast is fully resolved
|
||||||
// - apply nested stage III handlers
|
// - apply stage III pre handlers
|
||||||
// - apply filters on whole ast
|
// - apply global filters
|
||||||
|
// - apply stage III post handlers
|
||||||
//
|
//
|
||||||
//
|
//
|
||||||
// XXX RECURSION might be a good idea to limit recursion/nesting depth
|
// XXX RECURSION might be a good idea to limit recursion/nesting depth
|
||||||
// of inner merge(..)...
|
// of inner resolve(..)...
|
||||||
// XXX to allow nested filter blocks to self-exclude form global/uppaer
|
// XXX RENAME...
|
||||||
// filters would be nice to be able to do the filtering before
|
finalize: function(page, ast, state={}, nested_handlers={}, wait='wait'){
|
||||||
// we are fully resolved, i.e. after all the promises but before
|
|
||||||
// all the functions are gone from the ast...
|
|
||||||
// ...not yet sure how to get this through the merge(..)
|
|
||||||
merge: function(page, ast, state={}, nested_handlers={}, wait='wait'){
|
|
||||||
var that = this
|
var that = this
|
||||||
|
|
||||||
var stage3 = function(ast){
|
var stage3 = function(ast){
|
||||||
@ -818,46 +817,56 @@ module.BaseParser = {
|
|||||||
e.call(that, state)
|
e.call(that, state)
|
||||||
: e })
|
: e })
|
||||||
.flat() }
|
.flat() }
|
||||||
var merge = function(ast){
|
var resolve = function(ast){
|
||||||
return Promise.awaitOrRun(
|
return Promise.awaitOrRun(
|
||||||
...(state.unresolved ?? []),
|
...(state.unresolved ?? []),
|
||||||
function(){
|
function(){
|
||||||
delete state.unresolved
|
delete state.unresolved
|
||||||
// re-resolve...
|
// re-resolve...
|
||||||
ast = stage3(
|
ast = that.resolve(page, ast, state, nested_handlers)
|
||||||
that.resolve(page, ast, state, nested_handlers))
|
|
||||||
|
|
||||||
// NOTE: this is essentially running in the same frame
|
// NOTE: this is essentially running in the same frame
|
||||||
// as .resolve(..) above so there should not be
|
// as .resolve(..) above so there should not be
|
||||||
// any races to delete .unresolved...
|
// any races to delete .unresolved...
|
||||||
return state.unresolved ?
|
return state.unresolved ?
|
||||||
merge(ast)
|
resolve(ast)
|
||||||
: (ast ?? '').join('') }) }
|
: ast }) }
|
||||||
|
|
||||||
ast = stage3(
|
ast = this.resolve(page, ast, state, nested_handlers)
|
||||||
this.resolve(page, ast, state, nested_handlers))
|
|
||||||
|
|
||||||
return Promise.awaitOrRun(
|
return Promise.awaitOrRun(
|
||||||
state[wait],
|
...[state[wait]].flat(),
|
||||||
function(){
|
function(){
|
||||||
// NOTE: in an async world where any promised macro can
|
// NOTE: in an async world where any promised macro can
|
||||||
// call .exec(..) / .execNested(..) we can't trust
|
// call .exec(..) / .execNested(..) we can't trust
|
||||||
// the lack of .unresolved in state...
|
// the lack of .unresolved in state...
|
||||||
return that.applyFilters(
|
return Promise.awaitOrRun(
|
||||||
state.filters ?? [],
|
|
||||||
(state.unresolved
|
(state.unresolved
|
||||||
|| !that.isResolved(ast)) ?
|
|| !that.isResolved(ast)) ?
|
||||||
merge(ast)
|
resolve(ast)
|
||||||
: (ast ?? '').join(''),
|
: ast,
|
||||||
state) }) },
|
function(ast){
|
||||||
|
return (
|
||||||
|
// stage III post...
|
||||||
|
stage3(
|
||||||
|
that.applyFilters(
|
||||||
|
state.filters ?? [],
|
||||||
|
// stage III pre...
|
||||||
|
stage3( ast ),
|
||||||
|
state))) }) }) },
|
||||||
|
|
||||||
exec: function(page, ast, state={}, nested_handlers={}, wait='wait'){
|
exec: function(page, ast, state={}, nested_handlers={}, wait='wait'){
|
||||||
return this.merge(...arguments) },
|
return Promise.awaitOrRun(
|
||||||
|
this.finalize(...arguments),
|
||||||
|
function(res){
|
||||||
|
return res.join('') }) },
|
||||||
|
// XXX
|
||||||
execNested: function(page, ast, state={}, nested_handlers={}){
|
execNested: function(page, ast, state={}, nested_handlers={}){
|
||||||
//* XXX waitNested here deadlocks the parser -- not sure why...
|
/* XXX waitNested here deadlocks the parser -- not sure why...
|
||||||
|
//return this.exec(page, ast, state, nested_handlers, 'unresolved') },
|
||||||
return this.exec(page, ast, state, nested_handlers, 'waitNested') },
|
return this.exec(page, ast, state, nested_handlers, 'waitNested') },
|
||||||
/*/
|
/*/
|
||||||
return this.exec(page, ast, state, nested_handlers, 'unresolved') },
|
return this.exec(page, ast, state, nested_handlers, '') },
|
||||||
//*/
|
//*/
|
||||||
|
|
||||||
|
|
||||||
@ -870,7 +879,6 @@ module.BaseParser = {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// XXX do we need anything else like .doc, attrs???
|
|
||||||
var Macro =
|
var Macro =
|
||||||
module.Macro =
|
module.Macro =
|
||||||
function(spec, func){
|
function(spec, func){
|
||||||
@ -921,23 +929,23 @@ module.parser = {
|
|||||||
// detected.
|
// detected.
|
||||||
RECURSION_STRING: '',
|
RECURSION_STRING: '',
|
||||||
|
|
||||||
// XXX should this be here, in page, or both?
|
// Filters...
|
||||||
filters: {
|
//
|
||||||
upper: function(str){
|
// NOE: filters can't be named 'body', 'text', or 'clear' -- they
|
||||||
return str.toUpperCase() },
|
// will be shadowed by @filter(..)'s keyword arguments...
|
||||||
},
|
filters: {},
|
||||||
|
|
||||||
|
// Macros...
|
||||||
//
|
//
|
||||||
// <macro>(<args>, <body>, <state>){ .. }
|
// <macro>(<args>, <body>, <state>){ .. }
|
||||||
// -> undefined
|
// -> undefined
|
||||||
// -> <text>
|
// -> <text>
|
||||||
// -> <array>
|
// -> <array>
|
||||||
// -> <iterator>
|
// -> <iterator> XXX ???
|
||||||
|
// -> <promise>
|
||||||
// -> <func>(<state>)
|
// -> <func>(<state>)
|
||||||
// -> ...
|
// -> ...
|
||||||
//
|
//
|
||||||
// XXX do we need to make .macro.__proto__ module level object???
|
|
||||||
// XXX ASYNC make these support async page getters...
|
|
||||||
macros: {
|
macros: {
|
||||||
|
|
||||||
// Filter...
|
// Filter...
|
||||||
@ -953,14 +961,18 @@ module.parser = {
|
|||||||
// <filter> <filter-spec>
|
// <filter> <filter-spec>
|
||||||
// | -<filter> <filter-spec>
|
// | -<filter> <filter-spec>
|
||||||
//
|
//
|
||||||
// XXX need a way to exclude some filters in some nested locks...
|
// XXX should we include the global filters (current) or exclude
|
||||||
// XXX LOCAL_FILTERS do we combine local filters with state filters???
|
// them by default???
|
||||||
filter: function(page, args, body, state){
|
filter: Macro(
|
||||||
|
[['clear']],
|
||||||
|
function(page, args, body, state){
|
||||||
var that = this
|
var that = this
|
||||||
|
|
||||||
// get filters...
|
// get filters...
|
||||||
|
var clear = args.clear
|
||||||
delete args.text
|
delete args.text
|
||||||
delete args.body
|
delete args.body
|
||||||
|
delete args.clear
|
||||||
var filters = Object.keys(args)
|
var filters = Object.keys(args)
|
||||||
|
|
||||||
// local filter...
|
// local filter...
|
||||||
@ -974,17 +986,34 @@ module.parser = {
|
|||||||
// stage III
|
// stage III
|
||||||
return function(state){
|
return function(state){
|
||||||
return Promise.awaitOrRun(
|
return Promise.awaitOrRun(
|
||||||
that.merge(page, body, state),
|
|
||||||
function(body){
|
|
||||||
// apply the filters...
|
// apply the filters...
|
||||||
// XXX LOCAL_FILTERS combine with state.filters???
|
that.finalize(
|
||||||
return that.applyFilters(filters, body, state) }) } }
|
page,
|
||||||
|
body,
|
||||||
|
{
|
||||||
|
...state,
|
||||||
|
filters: clear ?
|
||||||
|
filters
|
||||||
|
: [...filters, ...state.filters ?? []],
|
||||||
|
}),
|
||||||
|
|
||||||
|
function(body){
|
||||||
|
// stage III post...
|
||||||
|
// NOTE: we are protecting the result from
|
||||||
|
// global filters...
|
||||||
|
return function(){
|
||||||
|
return body } }) } }
|
||||||
// global filter...
|
// global filter...
|
||||||
} else if(filters.length > 0){
|
} else if(filters.length > 0){
|
||||||
|
// NOTE: we are pushing this past the expand stage so as to
|
||||||
|
// avoid messing up all the small .exec*(..) calls used
|
||||||
|
// to handle macro attributes asn the like...
|
||||||
|
// ...but we need to do this before stage III so as not
|
||||||
|
// to race with applying local filters...
|
||||||
|
return function(state){
|
||||||
(state.filters = (state.filters ??= []))
|
(state.filters = (state.filters ??= []))
|
||||||
.push(...filters) }
|
.push(...filters) } } }),
|
||||||
|
|
||||||
return '' },
|
|
||||||
|
|
||||||
|
|
||||||
// Args...
|
// Args...
|
||||||
@ -1332,7 +1361,7 @@ module.parser = {
|
|||||||
var nested
|
var nested
|
||||||
return args.isolated ?
|
return args.isolated ?
|
||||||
//this.resolve(
|
//this.resolve(
|
||||||
this.merge(
|
this.finalize(
|
||||||
page,
|
page,
|
||||||
text,
|
text,
|
||||||
nested = args.isolated == 'partial' ?
|
nested = args.isolated == 'partial' ?
|
||||||
@ -1340,8 +1369,8 @@ module.parser = {
|
|||||||
: {})
|
: {})
|
||||||
// XXX FILTER need to localize target page
|
// XXX FILTER need to localize target page
|
||||||
// filters to it, somehow...
|
// filters to it, somehow...
|
||||||
// XXX should this be .merge(..)???
|
// XXX should this be .finalize(..)???
|
||||||
// .merge(..) here breaks things...
|
// .finalize(..) here breaks things...
|
||||||
: this.expand(page, text, state) }
|
: this.expand(page, text, state) }
|
||||||
|
|
||||||
var pageHandler =
|
var pageHandler =
|
||||||
|
|||||||
@ -11,6 +11,11 @@ var parser = require('../parser').parser
|
|||||||
|
|
||||||
//---------------------------------------------------------------------
|
//---------------------------------------------------------------------
|
||||||
|
|
||||||
|
;(parser.filters ??= {}).upper =
|
||||||
|
function(str){
|
||||||
|
return str.toUpperCase() }
|
||||||
|
|
||||||
|
|
||||||
var PAGES =
|
var PAGES =
|
||||||
module.exports.PAGES = {
|
module.exports.PAGES = {
|
||||||
'/blank': '',
|
'/blank': '',
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user