Compare commits

..

No commits in common. "8e501641ac8a769e8e07793b5e50aea30531749c" and "fa720d40fdff84237d967fd7b6028412afe10f8c" have entirely different histories.

View File

@ -270,19 +270,13 @@ module.BaseParser = {
: []), : []),
] }) ] })
.flat() }, .flat() },
filterBlocks: function(page, blocks, filter, state){
if(filter == null){
return blocks }
applyFilters: function(filters, str, state={}){ // XXX
var that = this
filters = this.normalizeFilters(filters) return blocks },
.filter(function(f){
return f in (that.filters ?? {})})
var handle = function(str){
return filters
.reduce(function(res, filter){
return that.filters[filter].call(that, str, state) }, str) }
return str instanceof Array ?
str.map(handle)
: handle(str) },
// Strip comments... // Strip comments...
@ -606,6 +600,7 @@ module.BaseParser = {
// states and the like, async/await can't... // states and the like, async/await can't...
// XXX Q: do we need generators? // XXX Q: do we need generators?
// XXX Handle errors... // XXX Handle errors...
fullAST: true,
// XXX this needs a careful rewrite of the .macros.* for the new scheme: // XXX this needs a careful rewrite of the .macros.* for the new scheme:
// - expand // - expand
// - "merge" // - "merge"
@ -692,8 +687,6 @@ module.BaseParser = {
delete state.waitNested } delete state.waitNested }
delete elem.resolving delete elem.resolving
elem.value = value elem.value = value
// XXX should we resolve to value or elem???
// ...elem seems more consistent...
return value }, return value },
function(err){ function(err){
state.errors ??= [] state.errors ??= []
@ -701,8 +694,14 @@ module.BaseParser = {
delete elem.resolving delete elem.resolving
elem.error = err }) elem.error = err })
// sync... // sync...
} else if('fullAST' in state ?
state.fullAST
: 'fullAST' in page ?
page.fullAST
: this.fullAST){
elem.value = res
} else { } else {
elem.value = res } elem = res }
elems.push(elem) } elems.push(elem) }
// cleanup... // cleanup...
@ -815,23 +814,8 @@ module.BaseParser = {
// XXX // XXX
}, },
// merge stage III... exec: function(page, ast, state={}, nested_handlers={}, wait='wait'){
//
// - ensure the ast is fully resolved
// - apply nested stage III handlers
// - apply filters on whole ast
//
//
merge: function(page, ast, state={}, nested_handlers={}, wait='wait'){
var that = this var that = this
var stage3 = function(ast){
return ast
.map(function(e){
return typeof(e) == 'function' ?
e.call(that, state)
: e })
.flat() }
// XXX might be a good idea to limit recursion depth here... // XXX might be a good idea to limit recursion depth here...
var merge = function(ast){ var merge = function(ast){
return Promise.awaitOrRun( return Promise.awaitOrRun(
@ -839,8 +823,7 @@ module.BaseParser = {
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
@ -849,25 +832,17 @@ module.BaseParser = {
merge(ast) merge(ast)
: (ast ?? '').join('') }) } : (ast ?? '').join('') }) }
ast = stage3(
this.resolve(page, ast, state, nested_handlers))
return Promise.awaitOrRun( return Promise.awaitOrRun(
this.resolve(page, ast, state, nested_handlers),
state[wait], state[wait],
function(){ function(ast){
// 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 (state.unresolved
state.filters ?? [],
(state.unresolved
|| !that.isResolved(ast)) ? || !that.isResolved(ast)) ?
merge(ast) merge(ast)
: (ast ?? '').join(''), : (ast ?? '').join('') }) },
state) }) },
exec: function(page, ast, state={}, nested_handlers={}, wait='wait'){
return this.merge(...arguments) },
// XXX how should this play with filters??? // XXX how should this play with filters???
@ -925,12 +900,6 @@ module.parser = {
INCLUDE_NEST_LIMIT: 20, INCLUDE_NEST_LIMIT: 20,
// XXX should this be here, in page, or both?
filters: {
upper: function(str){
return str.toUpperCase() },
},
// //
// <macro>(<args>, <body>, <state>){ .. } // <macro>(<args>, <body>, <state>){ .. }
// -> undefined // -> undefined
@ -957,39 +926,74 @@ 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 the rewrite:
// XXX BUG: RECURSION: this breaks @include(..)'s recursion tests... // - these need to be called after everything is done
filter: function(page, args, body, state){ // - globally in .exec(..) ???
// - localy after the item content is ready
// -> should we have and .onDone(..) event somwhere in the tree???
// ...this would be usefull for the callback renderer too...
//
// XXX BUG: this does not show any results:
// pwiki.exec('<filter test>moo test</filter>')
// -> ''
// while these do:
// pwiki.exec('<filter test/>moo test')
// -> 'moo TEST'
// await pwiki.exec('<filter test>moo test</filter>@var()')
// -> 'moo TEST'
// for more info see:
// file:///L:/work/pWiki/pwiki2.html#/Editors/Results
// XXX do we fix this or revise how/when filters work???
// ...including accounting for variables/expansions and the like...
// XXX REVISE...
// XXX UPDATE...
filter: function(parser, args, body, state, expand=true){
var that = this var that = this
delete args.text var outer = state.filters =
delete args.body state.filters ?? []
var filters = Object.keys(args) var local = Object.keys(args)
// local filter... // trigger quote-filter...
if(body){ var quote = local
// stage I .map(function(filter){
body = this.expand(page, body, state) return (that.filters[filter] ?? {})['quote'] ?? [] })
.flat()
quote.length > 0
&& parser.macros['quote-filter'].call(
this,
parser,
Object.fromEntries(Object.entries(quote)),
null,
state)
// local filters...
if(body != null){
// expand the body...
var ast = expand ?
this.__parser__.expand(this, body, state)
: body instanceof Array ?
body
// NOTE: wrapping the body in an array effectively
// escapes it from parsing...
: [body]
// stage II
return function(state){
body = that.resolve(page, body, state)
// stage III
return function(state){ return function(state){
// XXX can we loose stuff from state this way???
// ...at this stage it should more or less be static -- check!
return Promise.awaitOrRun( return Promise.awaitOrRun(
that.merge(page, body, state), // XXX how do we resolve the await loop?
function(body){ parser.execNested(this, ast, {
// apply the filters... ...state,
// XXX combine with state.filters??? filters: local.includes(this.ISOLATED_FILTERS) ?
return that.applyFilters(filters, body, state) }) } } local
: [...outer, ...local],
// global filter... }),
} else if(filters.length > 0){ function(res){
(state.filters = (state.filters ??= [])) return {data: res} }) }
.push(...filters) } // global filters...
} else {
return '' }, state.filters = [...outer, ...local] } },
// Args... // Args...
@ -1282,7 +1286,9 @@ module.parser = {
// not 100% correct manner focusing on path depth and ignoring // not 100% correct manner focusing on path depth and ignoring
// the context, this potentially can lead to false positives. // the context, this potentially can lead to false positives.
// //
// XXX FILTER do we skip includes from outer filters??? // XXX do we need the <context/> nested macro???
// XXX should this resolve join and/or body in the context of the
// included page or the outer page (current)???
// XXX add path recursion test to data -- fail if two paths resolve // XXX add path recursion test to data -- fail if two paths resolve
// to the same context... // to the same context...
// XXX need a way to make encode option transparent... // XXX need a way to make encode option transparent...
@ -1291,6 +1297,9 @@ module.parser = {
include: Macro( include: Macro(
['src', 'recursive', 'join', ['src', 'recursive', 'join',
['s', 'strict', 'isolated']], ['s', 'strict', 'isolated']],
// XXX thinking that reimplementing this is a bit less boring than
// refactoring, and should be cleaner...
// XXX if the src is empty return nothing...
// XXX need a wrapper protocol -- is this the level for it??? // XXX need a wrapper protocol -- is this the level for it???
// XXX page API used: // XXX page API used:
// .resolvePathVars(path) // .resolvePathVars(path)
@ -1328,7 +1337,6 @@ module.parser = {
handler ??= handler ??=
function(page, body, path, text, state){ function(page, body, path, text, state){
// re-include limit... // re-include limit...
//* XXX RECURSION
// XXX HACK??? // XXX HACK???
if( ++(state.included ??= {[path]: 0})[path] if( ++(state.included ??= {[path]: 0})[path]
> this.INCLUDE_NEST_LIMIT ?? 20){ > this.INCLUDE_NEST_LIMIT ?? 20){
@ -1349,24 +1357,19 @@ module.parser = {
throw new Error('Recursive macro: '+include_stack) } throw new Error('Recursive macro: '+include_stack) }
return that.expand(page, recursive, state) } return that.expand(page, recursive, state) }
include_stack.push(path) include_stack.push(path)
//*/
// XXX check cache??? // XXX check cache???
var nested var nested
var res = args.isolated ? var res = args.isolated ?
//this.resolve( this.resolve(
this.merge(
page, page,
text, text,
nested = args.isolated == 'partial' ? nested = args.isolated == 'partial' ?
serialize.partialDeepCopy(state) serialize.partialDeepCopy(state)
: {}) : {})
// XXX FILTER need to localize target page
// filters to it, somehow...
: this.expand(page, text, state) : this.expand(page, text, state)
//* XXX RECURSION
// handle recursion... // handle recursion...
Promise.awaitOrRun( Promise.awaitOrRun(
(nested ?? {}).waitAll, (nested ?? {}).waitAll,
@ -1378,7 +1381,6 @@ module.parser = {
if(state.include_stack.length == 0){ if(state.include_stack.length == 0){
delete state.include_stack delete state.include_stack
delete state.recursive } }) delete state.recursive } })
//*/
return res } return res }
@ -1489,10 +1491,6 @@ module.parser = {
quoting( quoting(
function(page, args, body, state){ function(page, args, body, state){
var that = this var that = this
var filters = (args.filter ?? '')
.split(/\s+/)
.filter(function(s){
return s.length > 0 })
return Promise.awaitOrRun( return Promise.awaitOrRun(
args.src args.src
&& this.execNested(page, args.src, state), && this.execNested(page, args.src, state),
@ -1509,9 +1507,10 @@ module.parser = {
function(text){ function(text){
return that.joinBlocks( return that.joinBlocks(
page, page,
that.applyFilters( that.filterBlocks(
filters, page,
text, text,
args.filter,
state), state),
args.join, args.join,
state) }) }) })), state) }) }) })),