filter mechanics now work, preparing to migrate rest of filters...

Signed-off-by: Alex A. Naanou <alex.nanou@gmail.com>
This commit is contained in:
Alex A. Naanou 2022-04-26 03:52:28 +03:00
parent 9efcb84734
commit 33ae0c690d

110
pwiki2.js
View File

@ -681,12 +681,14 @@ function*(lex, to=false, macros){
var Page = var Page =
module.Page = module.Page =
object.Constructor('Page', BasePage, { object.Constructor('Page', BasePage, {
SKIP_FILTERS: 'nofilters', //NO_FILTERS: 'nofilters',
ISOLATED_FILTERS: 'isolated',
// XXX might be a good idea to fix filter order... // XXX might be a good idea to fix filter order...
filters: { filters: {
// if this is used all other filters will be skipped (placeholder) // if this is used all other filters will be skipped (placeholder)
nofilters: function(source){ return source }, nofilters: function(source){ return source },
isolated: function(source){ return source },
// XXX move to docs... // XXX move to docs...
test: function(source){ test: function(source){
@ -698,6 +700,7 @@ object.Constructor('Page', BasePage, {
markdown: function(source){ markdown: function(source){
return source }, return source },
}, },
macros: { macros: {
// XXX move to docs... // XXX move to docs...
test: function*(args, body, state){ test: function*(args, body, state){
@ -715,24 +718,28 @@ object.Constructor('Page', BasePage, {
now: function(){ now: function(){
return ''+ Date.now() }, return ''+ Date.now() },
// XXX local filters??? //
// Example 1: // @filter(<filter-spec>)
// <filter markdown> ... </filter> // <filter <filter-spec>/>
// Example 2: //
// <filter> // <filter <filter-spec>>
// ... // ...
// @filter(markdown) // </filter>
// </filter> //
// XXX need to nest filter namespaces -- currently parent_filters // <filter-spec> ::=
// does not see filters defined after the block... // <filter> <filter-spec>
// | -<filter> <filter-spec>
//
// XXX support .NO_FILTERS ...
filter: function*(args, body, state){ filter: function*(args, body, state){
var filters = state.filters = var filters = state.filters =
state.filters ?? [] state.filters
// local filter... ?? []
// local filters...
if(body){ if(body){
var parent_filters = state.filters var parent_filters = state.filters
filters = state.filters = filters = state.filters =
[] } [parent_filters] }
// populate filters... // populate filters...
Object.values(args) Object.values(args)
.forEach(function(filter){ .forEach(function(filter){
@ -748,20 +755,24 @@ object.Constructor('Page', BasePage, {
&& filters.push(filter) }) && filters.push(filter) })
// local filters... // local filters...
if(body){ if(body){
// isolate from parent...
state.filters.includes(this.ISOLATED_FILTERS)
&& state.filters[0] instanceof Array
&& state.filters.shift()
// serialize the block for later processing... // serialize the block for later processing...
var res = { var res = {
filters: state.filters, filters: state.filters,
// XXX might be a good idea to simply ref the parent
// context here -- i.e. link filters into a chain...
parent_filters,
data: [...this.expand(body, state)], data: [...this.expand(body, state)],
} }
// restore global filters... // restore global filters...
state.filters = parent_filters state.filters = parent_filters
yield res } yield res }
return }, return },
source: function(args, body, state){
return args.src ?
this.get(src).render(state)
: '' },
include: function(){}, include: function(){},
source: function(){},
quote: function(){}, quote: function(){},
macro: function(){}, macro: function(){},
slot: function(){}, slot: function(){},
@ -804,38 +815,52 @@ object.Constructor('Page', BasePage, {
yield* res yield* res
} else { } else {
yield res } } }, yield res } } },
// XXX add a special filter to clear pending filters... // XXX add a special filter to clear pending filters... (???)
// XXX skip nested pre-filtered blocks... // XXX rename and use this instead of render...
postProcess: function(ast, state={}){ postProcess: function(ast, state={}){
var that = this var that = this
ast = ast
?? this.expand(null, state)
var _normalize = function(filters){
var skip = new Set()
return filters
.flat()
.tailUnique()
.filter(function(filter){
filter[0] == '-'
&& skip.add(filter.slice(1))
return filter[0] != '-' })
.filter(function(filter){
return !skip.has(filter) })}
return [...ast] return [...ast]
.map(function(section){ .map(function(section){
var filters = state.filters var filters = state.filters
// local filters... // nested filters...
if(typeof(section) != 'string'){ if(typeof(section) != 'string'){
// XXX also need to hanlde nested filters (no longer flat)... state.filters = _normalize(section.filters)
// XXX merge this with .parent_filters... var res = [...that.postProcess(section.data, state)]
filters = section.filters
section = [...that.postProcess(section.data, state)]
.flat() .flat()
.join('') } .join('')
return (filters state.filters = filters
// if this.SKIP_FILTERS is set and used then all other return res
// filters will be skipped... // local filters...
&& (!this.SKIP_FILTERS } else {
|| !filters.inculdes(this.SKIP_FILTERS))) ? return filters ?
// filter... _normalize(filters)
filters .reduce(function(res, filter){
.reduce(function(res, filter){ if(that.filters[filter] == null){
if(filter[0] == '-'){ throw new Error(
return res } '.postProcess(..): unsupported filter: '+ filter) }
if(that.filters[filter] == null){ return that.filters[filter].call(that, res) }, section)
throw new Error('.postProcess(..): unsupported filter: '+ filter) } : section } })
return that.filters[filter].call(that, res) }, section)
: section })
.flat() .flat()
.join('') }, .join('') },
render: function(state={}){
return this.postProcess(null, state) },
// raw page text... // raw page text...
// //
@ -857,10 +882,7 @@ object.Constructor('Page', BasePage, {
// XXX FUNC handle functions as pages... // XXX FUNC handle functions as pages...
// XXX need to support pattern pages... // XXX need to support pattern pages...
get text(){ get text(){
var state = {} return this.render() },
return this.postProcess(
this.expand(null, state),
state) },
set text(value){ set text(value){
this.store.update(this.location, {text: value}) }, this.store.update(this.location, {text: value}) },