mirror of
https://github.com/flynx/pWiki.git
synced 2025-10-30 18:40:08 +00:00
refactoring + include and source macros...
Signed-off-by: Alex A. Naanou <alex.nanou@gmail.com>
This commit is contained in:
parent
bdc1bbe00c
commit
2af87ac928
144
pwiki2.js
144
pwiki2.js
@ -522,16 +522,16 @@ module.parser = {
|
|||||||
].join('|') +')', 'smig'),
|
].join('|') +')', 'smig'),
|
||||||
|
|
||||||
|
|
||||||
// General parser API...
|
// Strip comments...
|
||||||
//
|
//
|
||||||
|
stripComments: function(str){
|
||||||
clearComments: function(str){
|
|
||||||
return str
|
return str
|
||||||
.replace(this.COMMENT_PATTERN,
|
.replace(this.COMMENT_PATTERN,
|
||||||
function(...a){
|
function(...a){
|
||||||
return a.pop().uncomment
|
return a.pop().uncomment
|
||||||
|| '' }) },
|
|| '' }) },
|
||||||
|
|
||||||
|
// Lexically split the string...
|
||||||
//
|
//
|
||||||
// <item> ::=
|
// <item> ::=
|
||||||
// <string>
|
// <string>
|
||||||
@ -551,15 +551,13 @@ module.parser = {
|
|||||||
//
|
//
|
||||||
//
|
//
|
||||||
// NOTE: this internally uses macros' keys to generate the lexing pattern.
|
// NOTE: this internally uses macros' keys to generate the lexing pattern.
|
||||||
//
|
|
||||||
// XXX feels a bit ugly...
|
|
||||||
lex: function*(page, str){
|
lex: function*(page, str){
|
||||||
str = str
|
str = str
|
||||||
?? page.raw
|
?? page.raw
|
||||||
// NOTE: we are doing a separate pass for comments to completely
|
// NOTE: we are doing a separate pass for comments to completely
|
||||||
// decouple them from the base macro syntax, making them fully
|
// decouple them from the base macro syntax, making them fully
|
||||||
// transparent...
|
// transparent...
|
||||||
str = this.clearComments(str)
|
str = this.stripComments(str)
|
||||||
|
|
||||||
// XXX should this be cached???
|
// XXX should this be cached???
|
||||||
var MACRO_PATTERN = new RegExp(
|
var MACRO_PATTERN = new RegExp(
|
||||||
@ -638,10 +636,7 @@ module.parser = {
|
|||||||
// ...
|
// ...
|
||||||
// }
|
// }
|
||||||
//
|
//
|
||||||
//
|
|
||||||
// NOTE: this internaly uses macros to check for propper nesting
|
// NOTE: this internaly uses macros to check for propper nesting
|
||||||
//
|
|
||||||
// XXX normalize lex to be a generator (???)
|
|
||||||
group: function*(page, lex, to=false){
|
group: function*(page, lex, to=false){
|
||||||
lex = lex
|
lex = lex
|
||||||
?? this.lex(page)
|
?? this.lex(page)
|
||||||
@ -682,6 +677,18 @@ module.parser = {
|
|||||||
|
|
||||||
// Expand macros...
|
// Expand macros...
|
||||||
//
|
//
|
||||||
|
// <item> ::=
|
||||||
|
// <string>
|
||||||
|
// // returned by .macros.filter(..)
|
||||||
|
// | {
|
||||||
|
// filters: [
|
||||||
|
// '<filter>'
|
||||||
|
// | '-<filter>',
|
||||||
|
// ...
|
||||||
|
// ],
|
||||||
|
// data: [ <item>, .. ],
|
||||||
|
// }
|
||||||
|
//
|
||||||
expand: function*(page, ast, state={}){
|
expand: function*(page, ast, state={}){
|
||||||
ast = ast == null ?
|
ast = ast == null ?
|
||||||
this.group(page)
|
this.group(page)
|
||||||
@ -715,16 +722,21 @@ module.parser = {
|
|||||||
// Fully parse a page...
|
// Fully parse a page...
|
||||||
//
|
//
|
||||||
// This runs in two stages:
|
// This runs in two stages:
|
||||||
// - expand the page text
|
// - expand the page
|
||||||
|
// - lex the page -- .lex(..)
|
||||||
|
// - group block elements -- .group(..)
|
||||||
|
// - expand macros -- .expand(..)
|
||||||
// - apply filters
|
// - apply filters
|
||||||
//
|
//
|
||||||
// XXX add a special filter to clear pending filters... (???)
|
// XXX add a special filter to clear pending filters... (???)
|
||||||
// XXX rename???
|
|
||||||
parse: function(page, ast, state={}){
|
parse: function(page, ast, state={}){
|
||||||
var that = this
|
var that = this
|
||||||
// XXX should we handle strings as input???
|
// XXX should we handle strings as input???
|
||||||
ast = ast
|
ast = ast
|
||||||
?? this.expand(page, null, state)
|
?? this.expand(page, null, state)
|
||||||
|
ast = typeof(ast) == 'string' ?
|
||||||
|
this.expand(page, ast, state)
|
||||||
|
: ast
|
||||||
|
|
||||||
var _normalize = function(filters){
|
var _normalize = function(filters){
|
||||||
var skip = new Set()
|
var skip = new Set()
|
||||||
@ -859,28 +871,82 @@ object.Constructor('Page', BasePage, {
|
|||||||
// serialize the block for later processing...
|
// serialize the block for later processing...
|
||||||
var res = {
|
var res = {
|
||||||
filters: state.filters,
|
filters: state.filters,
|
||||||
data: [...this.parser.expand(this, body, state)],
|
data: [...this.__parser__.expand(this, body, state)],
|
||||||
}
|
}
|
||||||
// restore global filters...
|
// restore global filters...
|
||||||
state.filters = parent_filters
|
state.filters = parent_filters
|
||||||
yield res }
|
yield res }
|
||||||
return },
|
return },
|
||||||
|
// XXX 'text' argument is changed to 'recursive'...
|
||||||
|
// XXX should we track recursion via the resolved (current) path
|
||||||
|
// or the given path???
|
||||||
|
// XXX should this be lazy???
|
||||||
|
include: function(args, body, state, key='included', handler){
|
||||||
|
// positional args...
|
||||||
|
var src = args.src || args[0]
|
||||||
|
var recursive = args.recursive || body
|
||||||
|
|
||||||
|
if(!src){
|
||||||
|
return '' }
|
||||||
|
|
||||||
|
handler = handler
|
||||||
|
?? function(){
|
||||||
|
return this.get(src)
|
||||||
|
.parse(
|
||||||
|
args.isolated ?
|
||||||
|
{[key]: state[key]}
|
||||||
|
: state) }
|
||||||
|
|
||||||
|
// handle recursion...
|
||||||
|
var parent_seen = state[key]
|
||||||
|
var seen = state[key] =
|
||||||
|
(state[key] ?? [this.location]).slice()
|
||||||
|
var target = this.match(src)
|
||||||
|
target = target instanceof Array ?
|
||||||
|
target.join(',')
|
||||||
|
: target
|
||||||
|
// recursion detected...
|
||||||
|
if(this.match() == this.match(src)
|
||||||
|
|| seen.includes(target)){
|
||||||
|
if(!recursive){
|
||||||
|
throw new Error(
|
||||||
|
'include: include recursion detected: '
|
||||||
|
+ seen.concat([target]).join(' -> ')) }
|
||||||
|
// have the 'recursive' arg...
|
||||||
|
return this.__parser__.parse(this, recursive, state) }
|
||||||
|
seen.push(target)
|
||||||
|
|
||||||
|
// load the included page...
|
||||||
|
var res = handler.call(this)
|
||||||
|
|
||||||
|
// restore previous include chain...
|
||||||
|
if(parent_seen){
|
||||||
|
state[key] = parent_seen
|
||||||
|
} else {
|
||||||
|
delete state[key] }
|
||||||
|
|
||||||
|
return res },
|
||||||
source: function(args, body, state){
|
source: function(args, body, state){
|
||||||
return args.src ?
|
var src = args.src || args[0]
|
||||||
this.get(src).render(state)
|
return this.macros.include.call(this,
|
||||||
: '' },
|
args, body, state, 'sources',
|
||||||
include: function(){},
|
function(){
|
||||||
quote: function(){},
|
return this.__parser__.parse(this, this.get(src).raw, state) }) },
|
||||||
macro: function(){},
|
macro: function(){},
|
||||||
slot: function(){},
|
slot: function(){},
|
||||||
|
|
||||||
|
// XXX quote what???
|
||||||
|
quote: function(){},
|
||||||
|
|
||||||
// nesting rules...
|
// nesting rules...
|
||||||
'else': ['macro'],
|
'else': ['macro'],
|
||||||
},
|
},
|
||||||
|
|
||||||
parser: module.parser,
|
// page parser...
|
||||||
|
//
|
||||||
|
__parser__: module.parser,
|
||||||
parse: function(state={}){
|
parse: function(state={}){
|
||||||
return this.parser.parse(this, null, state) },
|
return this.__parser__.parse(this, null, state) },
|
||||||
|
|
||||||
|
|
||||||
// raw page text...
|
// raw page text...
|
||||||
@ -939,19 +1005,35 @@ Page('/', '/',
|
|||||||
|
|
||||||
// XXX TEST...
|
// XXX TEST...
|
||||||
console.log('loading test page...')
|
console.log('loading test page...')
|
||||||
pwiki.update({
|
pwiki
|
||||||
|
.update({
|
||||||
|
location: '/page',
|
||||||
|
text: 'PAGE\n'
|
||||||
|
+'\n'
|
||||||
|
// XXX BUG this is parsed incorrectly -- macro pattern...
|
||||||
|
//+'@include(/test recursive="Recursion type 2 (<now/>)")\n',
|
||||||
|
+'@include(/test recursive="Recursion type 2 <now/>")\n',
|
||||||
|
})
|
||||||
|
.update({
|
||||||
|
location: '/other',
|
||||||
|
text: 'OTHER',
|
||||||
|
})
|
||||||
|
.update({
|
||||||
location: '/test',
|
location: '/test',
|
||||||
text: `
|
text: 'TEST\n'
|
||||||
Some test text...
|
+'Including /other #1: @include(/other)\n'
|
||||||
|
+'Including /other #2: @include(/other)\n'
|
||||||
@now()
|
+'\n'
|
||||||
|
// XXX BUG this is parsed incorrectly -- macro pattern...
|
||||||
<test>
|
//+'Including /test: @include(/test recursive="Recursion type 1 (<now/>)")\n'
|
||||||
some code...
|
+'Including /test: @include(/test recursive="Recursion type 1 <now/>")\n'
|
||||||
</test>
|
+'\n'
|
||||||
|
+'Including /page: @include(/page)\n'
|
||||||
@filter(test)`,
|
+'\n'
|
||||||
})
|
+'Including /: \\@include(/)\n'
|
||||||
|
+'\n'
|
||||||
|
+'@filter(test)',
|
||||||
|
})
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user