From 67db497eab62a3fc7e9d0916b225d26f7920e870 Mon Sep 17 00:00:00 2001 From: "Alex A. Naanou" Date: Sun, 5 Jul 2026 14:56:45 +0300 Subject: [PATCH] refactoring parser -- still not 100%... Signed-off-by: Alex A. Naanou --- v3/package-lock.json | 12 ++-- v3/pwiki/parser.js | 130 ++++++++++++++++++++++++---------------- v3/pwiki/test/parser.js | 5 +- 3 files changed, 88 insertions(+), 59 deletions(-) diff --git a/v3/package-lock.json b/v3/package-lock.json index 9624fbe..4916702 100644 --- a/v3/package-lock.json +++ b/v3/package-lock.json @@ -32,9 +32,9 @@ } }, "node_modules/brace-expansion": { - "version": "5.0.6", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-5.0.6.tgz", - "integrity": "sha512-kLpxurY4Z4r9sgMsyG0Z9uzsBlgiU/EFKhj/h91/8yHu0edo7XuixOIH3VcJ8kkxs6/jPzoI6U9Vj3WqbMQ94g==", + "version": "5.0.7", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-5.0.7.tgz", + "integrity": "sha512-7oFy703dxfY3/NLxC1fh2SUCQ0H9rmAY+5EpDVfXjUTTs+HEwR2nYaqLv+GWcTsumwxPfiz6CzCNkwXwBUwqCA==", "license": "MIT", "dependencies": { "balanced-match": "^4.0.2" @@ -231,9 +231,9 @@ } }, "node_modules/ig-types": { - "version": "6.26.2", - "resolved": "https://registry.npmjs.org/ig-types/-/ig-types-6.26.2.tgz", - "integrity": "sha512-VGg8MVmpblVCmZK52bJcDtPG3uRFiEyPnlDEIJv3MymTm+aUNWR/Th20NU2wfGV/Ux3KlsbGlhe+0c9ZKTYPDw==", + "version": "6.26.3", + "resolved": "https://registry.npmjs.org/ig-types/-/ig-types-6.26.3.tgz", + "integrity": "sha512-WDGHnC2up/7x5agsS2HfQbegfY97mMGM4xNv1HII3OiidcoPFDjp7nLdOOsWfZOtXA7nGWdAriGeVCOOJxEhew==", "license": "BSD-3-Clause", "dependencies": { "ig-object": "^6.0.0", diff --git a/v3/pwiki/parser.js b/v3/pwiki/parser.js index 7eb71cd..f11ad40 100644 --- a/v3/pwiki/parser.js +++ b/v3/pwiki/parser.js @@ -1300,19 +1300,6 @@ module.parser = { return Promise.awaitOrRun( this.parseNested(page, src, state), function(src){ - // check for recursion... - // XXX will this work for @source(..)??? - var stack = state.include_stack ??= [] - if(stack.includes(src)){ - if(!recursive){ - throw new Error('Recursive macro: '+stack) } - return that.expand(page, recursive, state) } - stack.push(src) - - var cache = state.cache ??= {} - if(cache[src]){ - return cache[src] } - // XXX should this be a tree?? // ...need to at least split direct and // indirect dependencies... @@ -1325,9 +1312,18 @@ module.parser = { // content handler... handler ??= - function(page, src, text, state){ - page = page.get(src) - return args.isolated ? + function(page, body, path, text, state){ + // check for recursion... + var include_stack = state.include_stack ??= [] + if(include_stack.includes(path)){ + if(!recursive){ + throw new Error('Recursive macro: '+include_stack) } + return that.expand(page, recursive, state) } + include_stack.push(path) + + // XXX check cache??? + + var res = args.isolated ? this.resolve( page, text, @@ -1335,38 +1331,30 @@ module.parser = { args.isolated == 'partial' ? serialize.partialDeepCopy(state) : {}, - {stack: state.stack ?? []})) - : this.expand(page, text, state) } + {include_stack})) + : this.expand(page, text, state) + + // handle recursion... + return Promise.awaitOrRun( + res, + function(){ + state.include_stack.at(-1) == src + && state.include_stack.pop() + // cleanup... + if(state.include_stack.length == 0){ + delete state.include_stack + delete state.recursive } + + return res }) } var pageHandler = function([path, text]){ - var content_handled = false - return body ? - // handle body / ... - Promise.awaitOrRun( - that.expand(page.get(path), body, state, - { content: function(){ - content_handled = true - return text = handler.call(that, page, src, text, state) } }), - function(text){ - // if no present we still - // need to handle the included page... - content_handled - || handler.call(that, page, src, text, state) - return text }) - // place as-is... - : handler.call(that, page, src, text, state) } - var resultHandler = - function(pages){ - state.include_stack.at(-1) == src - && state.include_stack.pop() - // cleanup... - if(state.include_stack.length == 0){ - delete state.include_stack - delete state.recursive } - // cache the final result... - cache[src] = pages - return pages } + // handle nested promises... + return Promise.awaitOrRun( + text, + function(text){ + return handler.call(that, page, body, path, text, state) }) } + // get and run things... return Promise.awaitOrRun( @@ -1374,23 +1362,32 @@ module.parser = { page.get(src).raw, function(paths, texts){ texts = + // XXX how do we handle paths returning non-strings??? // special case: list page... paths.length == 1 && texts instanceof Array ? [texts] : texts instanceof Array ? texts - : [texts] + : [texts ?? ''] return Promise.awaitOrRun( // handle pages... Promise .iter( - Array - .zip(paths, texts) - .map(pageHandler)) + that.joinBlocks( + page, + Array + .zip(paths, texts) + .map(pageHandler), + args.join, + state)) .flat() .sync(), - resultHandler ) }) }) })), + function(pages){ + /* XXX cache the final result... + cache[src] = pages + //*/ + return pages }) }) }) })), // NOTE: the main difference between this and @include is that // this renders the src in the context of current page while @@ -1559,7 +1556,38 @@ module.parser = { body = (state.macros ?? {})[name] } return args.src && body ? // run macro... - that.macros.include.call(that, page, args, body, state) + that.macros.include.call(that, page, args, body, state, + function(page, body, path, text, state){ + var that = this + + var handle = function(page, text, state){ + return args.isolated ? + that.resolve( + page, + text, + Object.assign( + args.isolated == 'partial' ? + serialize.partialDeepCopy(state) + : {}, + {include_stack: state.include_stack ?? []})) + : that.expand(page, text, state) } + + //var content_handled = false + return body ? + // handle body / ... + Promise.awaitOrRun( + that.expand(page.get(path), body, state, + { content: function(){ + content_handled = true + return text = handle(page, text, state) } }), + function(text){ + // if no present we still + // need to handle the included page... + //content_handled + // || handle.call(that, page, text, state) + return text }) + // place as-is... + : handle(page, text, state) }) : '' }) })), // nesting rules... diff --git a/v3/pwiki/test/parser.js b/v3/pwiki/test/parser.js index a8fd31b..d098c49 100755 --- a/v3/pwiki/test/parser.js +++ b/v3/pwiki/test/parser.js @@ -92,7 +92,7 @@ module.exports.P = { .iter(res) .sync() }, /*/ - res }, + : res }, //*/ // XXX should this return an arrya for a multi-match??? @@ -284,13 +284,14 @@ test.Setups({ ], } }, //*/ - // content... + /*/ XXX content... include_content: function(assert, path='/page'){ return { page: P, code: [ '[[ ]]', '[[ '+ P.get(path).raw +' ]]', ], } }, + //*/ // XXX // recursion...