mirror of
				https://github.com/flynx/pWiki.git
				synced 2025-10-31 02:50: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
					
				
							
								
								
									
										146
									
								
								pwiki2.js
									
									
									
									
									
								
							
							
						
						
									
										146
									
								
								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 | ||||||
| 	location: '/test', | 	.update({ | ||||||
| 	text: ` | 		location: '/page', | ||||||
| 	Some test text... | 		text: 'PAGE\n' | ||||||
| 
 | 			+'\n' | ||||||
| 	@now() | 			// XXX BUG this is parsed incorrectly -- macro pattern...
 | ||||||
| 
 | 			//+'@include(/test recursive="Recursion type 2 (<now/>)")\n',
 | ||||||
| 	<test> | 			+'@include(/test recursive="Recursion type 2 <now/>")\n', | ||||||
| 	some code... | 	}) | ||||||
| 	</test> | 	.update({ | ||||||
| 	 | 		location: '/other', | ||||||
| 	@filter(test)`,
 | 		text: 'OTHER', | ||||||
| }) | 	}) | ||||||
|  | 	.update({ | ||||||
|  | 		location: '/test', | ||||||
|  | 		text: 'TEST\n' | ||||||
|  | 			+'Including /other #1: @include(/other)\n' | ||||||
|  | 			+'Including /other #2: @include(/other)\n' | ||||||
|  | 			+'\n' | ||||||
|  | 			// XXX BUG this is parsed incorrectly -- macro pattern...
 | ||||||
|  | 			//+'Including /test: @include(/test recursive="Recursion type 1 (<now/>)")\n'
 | ||||||
|  | 			+'Including /test: @include(/test recursive="Recursion type 1 <now/>")\n' | ||||||
|  | 			+'\n' | ||||||
|  | 			+'Including /page: @include(/page)\n' | ||||||
|  | 			+'\n' | ||||||
|  | 			+'Including /: \\@include(/)\n' | ||||||
|  | 			+'\n' | ||||||
|  | 			+'@filter(test)', | ||||||
|  | 	}) | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
|  | |||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user