tweaks...

Signed-off-by: Alex A. Naanou <alex.nanou@gmail.com>
This commit is contained in:
Alex A. Naanou 2022-05-18 18:13:19 +03:00
parent 9a40941cfc
commit c0cd9a4000
4 changed files with 68 additions and 17 deletions

2
bootstrap.js vendored

File diff suppressed because one or more lines are too long

2
bootstrap/Theme/CLI/tree.txt Executable file
View File

@ -0,0 +1,2 @@
@source(../name)<macro src="../*">
<include src="@source(./path)/tree" recursive="..."/></macro>

View File

@ -79,6 +79,7 @@ module.path = {
], ],
SEARCH_PATHS: [ SEARCH_PATHS: [
'./Theme/CLI',
'./Templates', './Templates',
'/System', '/System',
], ],
@ -982,7 +983,8 @@ module.BaseParser = {
// NOTE: arg pre-parsing is dome by .lex(..) but at that stage we do not // NOTE: arg pre-parsing is dome by .lex(..) but at that stage we do not
// yet touch the actual macros (we need them to get the .arg_spec) // yet touch the actual macros (we need them to get the .arg_spec)
// so the actual parsing is done in .expand(..) // so the actual parsing is done in .expand(..)
parseArgs: function(spec, args){ parseArgs: function(spec, args, state){
var that = this
// spec... // spec...
var order = spec.slice() var order = spec.slice()
var bools = new Set( var bools = new Set(
@ -997,7 +999,7 @@ module.BaseParser = {
var pos = Object.entries(args) var pos = Object.entries(args)
// stage 1: populate res with explicit data and place the rest in pos... // stage 1: populate res with explicit data and place the rest in pos...
.reduce(function(pos, [key, value]){ .reduce(function(pos, [key, value]){
/^[0-9]+$/.test(key) ? ;/^[0-9]+$/.test(key) ?
(bools.has(value) ? (bools.has(value) ?
// bool... // bool...
(res[value] = true) (res[value] = true)
@ -1247,7 +1249,8 @@ module.BaseParser = {
args = this.parseArgs.call(page, args = this.parseArgs.call(page,
page.macros[name].arg_spec page.macros[name].arg_spec
?? [], ?? [],
args) args,
state)
// call... // call...
var res = var res =
page.macros[name].call(page, args, body, state, value) page.macros[name].call(page, args, body, state, value)
@ -1472,7 +1475,7 @@ object.Constructor('Page', BasePage, {
var outer_filters = state.filters var outer_filters = state.filters
state.filters = this.__parser__.normalizeFilters(filters) state.filters = this.__parser__.normalizeFilters(filters)
var res = var res =
[...this.__parser__.parse(this, ast, state)] [...this.parse(ast, state)]
.flat() .flat()
.join('') .join('')
state.filters = outer_filters state.filters = outer_filters
@ -1488,8 +1491,7 @@ object.Constructor('Page', BasePage, {
// </include> // </include>
// //
// XXX 'text' argument is changed to 'recursive'... // XXX 'text' argument is changed to 'recursive'...
// XXX should we track recursion via the resolved (current) path // XXX revise recursion checks....
// or the given path???
// XXX should this be lazy??? // XXX should this be lazy???
include: Macro( include: Macro(
['src', 'recursive', ['isolated']], ['src', 'recursive', ['isolated']],
@ -1500,7 +1502,9 @@ object.Constructor('Page', BasePage, {
var isolated = args.isolated var isolated = args.isolated
if(!src){ if(!src){
return '' } return }
// parse arg values...
src = this.parse(src, state)
handler = handler handler = handler
?? function(){ ?? function(){
@ -1520,14 +1524,16 @@ object.Constructor('Page', BasePage, {
: target : target
// recursion detected... // recursion detected...
if(this.match() == this.match(src) if(this.match() == this.match(src)
|| seen.includes(target)){ || seen.includes(src)){
//* XXX this prevents recursion...
if(!recursive){ if(!recursive){
throw new Error( throw new Error(
'include: include recursion detected: ' 'include: include recursion detected: '
+ seen.concat([target]).join(' -> ')) } + seen.concat([src]).join(' -> ')) }
//*/
// have the 'recursive' arg... // have the 'recursive' arg...
return this.__parser__.parse(this, recursive, state) } return this.parse(recursive, state) }
seen.push(target) seen.push(src)
// load the included page... // load the included page...
var res = handler.call(this) var res = handler.call(this)
@ -1543,10 +1549,14 @@ object.Constructor('Page', BasePage, {
['src'], ['src'],
function(args, body, state){ function(args, body, state){
var src = args.src var src = args.src
// parse arg values...
src = src ?
this.parse(src, state)
: src
return this.macros.include.call(this, return this.macros.include.call(this,
args, body, state, 'sources', args, body, state, 'sources',
function(){ function(){
return this.__parser__.parse(this, this.get(src).raw +'', state) }) }), return this.parse(this.get(src).raw +'', state) }) }),
// //
// @quote(<src>) // @quote(<src>)
// //
@ -1573,6 +1583,10 @@ object.Constructor('Page', BasePage, {
var text = args.text var text = args.text
?? body ?? body
?? [] ?? []
// parse arg values...
src = src ?
this.parse(src, state)
: src
text = src ? text = src ?
// source page... // source page...
this.get(src).raw this.get(src).raw
@ -1652,6 +1666,11 @@ object.Constructor('Page', BasePage, {
state.slots state.slots
?? {} ?? {}
// parse arg values...
name = name ?
this.parse(name, state)
: name
//var hidden = name in slots //var hidden = name in slots
// XXX EXPERIMENTAL // XXX EXPERIMENTAL
var hidden = var hidden =
@ -1709,6 +1728,7 @@ object.Constructor('Page', BasePage, {
: text : text
if(name){ if(name){
name = this.parse(name, state)
// define new named macro... // define new named macro...
if(text){ if(text){
;(state.macros = state.macros ?? {})[name] = text ;(state.macros = state.macros ?? {})[name] = text
@ -1718,6 +1738,7 @@ object.Constructor('Page', BasePage, {
text = state.macros[name] } } text = state.macros[name] } }
if(src){ if(src){
src = this.parse(src, state)
var pages = this.get(src).each() var pages = this.get(src).each()
// no matching pages -> get the else block... // no matching pages -> get the else block...
if(pages.length == 0 if(pages.length == 0
@ -1764,10 +1785,18 @@ object.Constructor('Page', BasePage, {
// page parser... // page parser...
// //
__parser__: module.parser, __parser__: module.parser,
parse: function(state={}){ parse: function(text, state){
// .parser(<state>)
if(arguments.length == 1
&& text instanceof Object
&& !(text instanceof Array)){
state = text
text = null }
// NOTE: we do not need to pass this.raw here but it is still // NOTE: we do not need to pass this.raw here but it is still
// here for illustration... // here for illustration...
return this.__parser__.parse(this, this.raw, state) }, return this.__parser__.parse(this,
text ?? this.raw,
state ?? {}) },
// raw page text... // raw page text...
@ -1979,6 +2008,26 @@ pwiki
+'\n' +'\n'
+'@filter(test)', +'@filter(test)',
}) })
.update({
location: '/test/a',
text: 'a',
})
.update({
location: '/test/b',
text: 'b',
})
.update({
location: '/test/c',
text: 'c',
})
.update({
location: '/test/c/x',
text: 'x',
})
.update({
location: '/test/c/y',
text: 'y',
})
//*/ //*/

View File

@ -22,11 +22,11 @@ typeof(module) != "undefined"
// XXX add support for json... // XXX add support for json...
glob('bootstrap/**/*.@(tpl|md|css|html)') glob('bootstrap/**/*.@(tpl|md|css|html|txt)')
.on('match', function(path){ .on('match', function(path){
var p = path var p = path
.replace('bootstrap/', '') .replace('bootstrap/', '')
.replace(/\.(json|txt|md|css|html)/, '') .replace(/\.(json|txt|md|css|html|txt)/, '')
console.log('Found:', p) console.log('Found:', p)
bootstrap[p] = { bootstrap[p] = {
text: fs.readFileSync(path).toString(), text: fs.readFileSync(path).toString(),