@macro(..) is now a generator + generalized pattern/list handling as .asPages()...

Signed-off-by: Alex A. Naanou <alex.nanou@gmail.com>
This commit is contained in:
Alex A. Naanou 2022-08-19 19:40:28 +03:00
parent d7cc854781
commit f67a623f10
3 changed files with 50 additions and 51 deletions

View File

@ -305,6 +305,8 @@ object.Constructor('BasePage', {
for(var path of paths){ for(var path of paths){
yield this.get('/'+ path) } }, yield this.get('/'+ path) } },
[Symbol.asyncIterator]: async function*(){
yield* this.each() },
map: async function(func){ map: async function(func){
return this.each().map(func) }, return this.each().map(func) },
@ -658,11 +660,8 @@ object.Constructor('Page', BasePage, {
// At the moment nested recursion is checked in a fast but // At the moment nested recursion is checked in a fast but
// 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 make this a generator...
// XXX should we use .__parser__.expand(..) instead of .parse(..) ???
include: Macro( include: Macro(
['src', 'recursive', 'join', ['isolated']], ['src', 'recursive', 'join', ['strict', 'nonstrict', 'isolated']],
async function*(args, body, state, key='included', handler){ async function*(args, body, state, key='included', handler){
var macro = 'include' var macro = 'include'
if(typeof(args) == 'string'){ if(typeof(args) == 'string'){
@ -675,6 +674,8 @@ object.Constructor('Page', BasePage, {
return } return }
var recursive = args.recursive ?? body var recursive = args.recursive ?? body
var isolated = args.isolated var isolated = args.isolated
var strict = args.strict
&& !args.nonstrict
var join = args.join var join = args.join
&& await base.parse(args.join, state) && await base.parse(args.join, state)
@ -688,7 +689,7 @@ object.Constructor('Page', BasePage, {
.parse(state) } .parse(state) }
var first = true var first = true
for await (var page of this.get(src).each()){ for await (var page of this.get(src).asPages(strict)){
if(join && !first){ if(join && !first){
yield join } yield join }
first = false first = false
@ -774,7 +775,7 @@ object.Constructor('Page', BasePage, {
: src : src
var pages = src ? var pages = src ?
this.get(src).each() this.get(src).asPages()
: text instanceof Array ? : text instanceof Array ?
[text.join('')] [text.join('')]
: typeof(text) == 'string' ? : typeof(text) == 'string' ?
@ -891,6 +892,7 @@ object.Constructor('Page', BasePage, {
// show first instance... // show first instance...
: name in slots) : name in slots)
// set slot value...
var stack = [] var stack = []
slots[name] slots[name]
&& stack.push(slots[name]) && stack.push(slots[name])
@ -901,7 +903,6 @@ object.Constructor('Page', BasePage, {
slot = slots[name] = slot = slots[name] =
slots[name] slots[name]
?? slot ?? slot
// handle <content/>... // handle <content/>...
for(prev of stack){ for(prev of stack){
// get the first <content/> // get the first <content/>
@ -917,14 +918,12 @@ object.Constructor('Page', BasePage, {
.filter(function(e){ .filter(function(e){
return typeof(e) != 'function' return typeof(e) != 'function'
|| e.slot != name }) ) } || e.slot != name }) ) }
return hidden ? return hidden ?
'' ''
: Object.assign( : Object.assign(
function(state){ function(state){
return state.slots[name] }, return state.slots[name] },
{slot: name}) }), {slot: name}) }),
//*/
'content': ['slot'], 'content': ['slot'],
// //
@ -952,18 +951,14 @@ object.Constructor('Page', BasePage, {
// NOTE: if both strict and nonstrict are given the later takes // NOTE: if both strict and nonstrict are given the later takes
// precedence. // precedence.
// //
// XXX GENERATOR make this a generator...
// XXX ELSE_PRIO should else attr take priority over the <else> tag???
// ...currently as with text=... the attr takes priority...
// XXX SORT sorting not implemented yet.... // XXX SORT sorting not implemented yet....
// XXX should support arrays...
// e.g.
// <macro src="/test/*/resolved"> ... </macro>
// ...does not work yet...
// ....currently resolved returns promises....
macro: Macro( macro: Macro(
['name', 'src', 'sort', 'text', 'join', 'else', ['strict', 'nonstrict']], ['name', 'src', 'sort', 'text', 'join', 'else', ['strict', 'nonstrict']],
// XXX GENERATOR...
async function*(args, body, state){
/*/
async function(args, body, state){ async function(args, body, state){
//*/
var that = this var that = this
var name = args.name //?? args[0] var name = args.name //?? args[0]
var src = args.src var src = args.src
@ -1014,37 +1009,22 @@ object.Constructor('Page', BasePage, {
if(src){ if(src){
src = await base.parse(src, state) src = await base.parse(src, state)
var pages = this.get(src, strict)
pages = await pages.isArray ? var join = _getBlock('join')
// XXX should we wrap this in pages...
(await pages.raw) // expand matches...
.map(function(data){ var first = true
return that.virtual({text: data}) }) for await(var page of this.get(src).asPages(strict)){
: await pages.each() if(join && !first){
// no matching pages -> get the else block... yield join }
if(pages.length == 0 first = false
yield this.__parser__.expand(page, text, state) }
// else...
if(first
&& (text || args['else'])){ && (text || args['else'])){
var else_block = _getBlock('else') var else_block = _getBlock('else')
return else_block ? if(else_block){
await this.__parser__.expand(this, else_block, state) yield this.__parser__.expand(this, else_block, state) } } } }),
: undefined }
// sort pages...
// XXX SORT
if(sort.length > 0){
console.log('XXX: macro sort: not implemented') }
var join_block = _getBlock('join')
// apply macro text...
var res = pages
.map(function(page){
return that.__parser__.expand(page, text, state) })
return join_block ?
res.between(
// render join block relative to the path before the first '*'...
await that.__parser__.expand(base, join_block, state))
: res } }),
// nesting rules... // nesting rules...
'else': ['macro'], 'else': ['macro'],
@ -1126,6 +1106,27 @@ object.Constructor('Page', BasePage, {
this.__update__({text: value}) }, this.__update__({text: value}) },
//this.onTextUpdate(value) }, //this.onTextUpdate(value) },
// iterate matches or content list as pages...
//
// XXX revise name...
asPages: async function*(path='.', strict=false){
if(path === true
|| path === false){
strict = path
path = '.' }
var page = this.get(path, strict)
// handle lists in pages (actions, ... etc.)...
if(!page.isPattern){
var raw = await page.raw
yield* raw instanceof Array ?
raw
.map(function(p){
return page.virtual({text: p}) })
: [page]
// each...
} else {
yield* page } },
// expanded page text... // expanded page text...
// //
// NOTE: this uses .PAGE_TEMPLATE to render the page. // NOTE: this uses .PAGE_TEMPLATE to render the page.

View File

@ -460,10 +460,10 @@ module.BaseParser = {
/*/ /*/
for(var e of await ast){ for(var e of await ast){
//*/ //*/
// expand delayed sections...
e = typeof(e) == 'function' ? e = typeof(e) == 'function' ?
e.call(page, state) e.call(page, state)
: e : e
// expand arrays... // expand arrays...
if(e instanceof Array if(e instanceof Array
| e instanceof types.Generator){ | e instanceof types.Generator){

View File

@ -22,15 +22,13 @@
* @include(..) -- DONE * @include(..) -- DONE
* @source(..) -- DONE * @source(..) -- DONE
* @quote(..) -- DONE * @quote(..) -- DONE
* @macro(..) -- * @macro(..) -- DONE
* 3) experiment with back-drivable generators...
* this can be implemented/tested in parallel and integrated into
* the main pipeline if proven successful...
* XXX ranges in pattern paths -- page-size=X page=Y | from=X to=Y / ... * XXX ranges in pattern paths -- page-size=X page=Y | from=X to=Y / ...
* ...url syntax??? * ...url syntax???
* XXX differenced in behaviour between _abc and abc, either need to make * XXX differenced in behaviour between _abc and abc, either need to make
* them the same or document the differences and the reasons behind * them the same or document the differences and the reasons behind
* them... * them...
* XXX add support for <join> tag in include/source/quote???
* XXX BUG?: markdown: when parsing chunks each chunk gets an open/closed * XXX BUG?: markdown: when parsing chunks each chunk gets an open/closed
* <p> inserted at start/end -- this breaks stuff returned by macros... * <p> inserted at start/end -- this breaks stuff returned by macros...
* ...there are two ways to dance around this: * ...there are two ways to dance around this: