| 
									
										
										
										
											2022-08-04 11:00:21 +03:00
										 |  |  | /********************************************************************** | 
					
						
							|  |  |  | *  | 
					
						
							|  |  |  | * | 
					
						
							|  |  |  | * | 
					
						
							|  |  |  | **********************************************************************/ | 
					
						
							|  |  |  | ((typeof define)[0]=='u'?function(f){module.exports=f(require)}:define) | 
					
						
							|  |  |  | (function(require){ var module={} // make module AMD/node compatible...
 | 
					
						
							|  |  |  | /*********************************************************************/ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | var object = require('ig-object') | 
					
						
							|  |  |  | var types = require('ig-types') | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-11-26 13:22:10 +03:00
										 |  |  | // XXX this should be optional...
 | 
					
						
							|  |  |  | // XXX is this a good idea???
 | 
					
						
							|  |  |  | //var dateparser = require('any-date-parser')
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-08-05 18:21:18 +03:00
										 |  |  | var pwpath = require('./path') | 
					
						
							| 
									
										
										
										
											2022-08-04 11:00:21 +03:00
										 |  |  | var parser = require('./parser') | 
					
						
							| 
									
										
										
										
											2022-08-04 14:29:25 +03:00
										 |  |  | var filters = require('./filters/base') | 
					
						
							|  |  |  | var markdown = require('./filters/markdown') | 
					
						
							| 
									
										
										
										
											2022-08-04 11:00:21 +03:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | //---------------------------------------------------------------------
 | 
					
						
							|  |  |  | // Page...
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | var relProxy =  | 
					
						
							|  |  |  | function(name){ | 
					
						
							| 
									
										
										
										
											2022-09-07 16:37:26 +03:00
										 |  |  | 	var func = function(path='.:$ARGS', ...args){ | 
					
						
							| 
									
										
										
										
											2022-09-08 01:56:55 +03:00
										 |  |  | 		path = this.resolvePathVars(path) | 
					
						
							| 
									
										
										
										
											2022-08-04 11:00:21 +03:00
										 |  |  | 		return this.store[name]( | 
					
						
							| 
									
										
										
										
											2022-08-31 15:46:51 +03:00
										 |  |  | 			pwpath.relative(this.path, path),  | 
					
						
							| 
									
										
										
										
											2022-08-04 11:00:21 +03:00
										 |  |  | 			...args) }  | 
					
						
							|  |  |  | 	Object.defineProperty(func, 'name', {value: name}) | 
					
						
							|  |  |  | 	return func }  | 
					
						
							|  |  |  | var relMatchProxy =  | 
					
						
							|  |  |  | function(name){ | 
					
						
							| 
									
										
										
										
											2022-09-07 16:37:26 +03:00
										 |  |  | 	var func = function(path='.:$ARGS', strict=this.strict){ | 
					
						
							| 
									
										
										
										
											2022-08-04 11:00:21 +03:00
										 |  |  | 		if(path === true || path === false){ | 
					
						
							|  |  |  | 			strict = path | 
					
						
							| 
									
										
										
										
											2022-09-07 16:37:26 +03:00
										 |  |  | 			path = '.:$ARGS' } | 
					
						
							| 
									
										
										
										
											2022-09-08 01:56:55 +03:00
										 |  |  | 		path = this.resolvePathVars(path) | 
					
						
							| 
									
										
										
										
											2022-08-04 11:00:21 +03:00
										 |  |  | 		return this.store[name]( | 
					
						
							| 
									
										
										
										
											2022-08-31 15:46:51 +03:00
										 |  |  | 			pwpath.relative(this.path, path),  | 
					
						
							| 
									
										
										
										
											2022-08-04 11:00:21 +03:00
										 |  |  | 			strict) }  | 
					
						
							|  |  |  | 	Object.defineProperty(func, 'name', {value: name}) | 
					
						
							|  |  |  | 	return func } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-08-04 14:29:25 +03:00
										 |  |  | 
 | 
					
						
							|  |  |  | // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-08-04 11:00:21 +03:00
										 |  |  | var BasePage = | 
					
						
							|  |  |  | module.BasePage =  | 
					
						
							|  |  |  | object.Constructor('BasePage', { | 
					
						
							|  |  |  | 	// root page used to clone new instances via the .clone(..) method...
 | 
					
						
							|  |  |  | 	//root: undefined,
 | 
					
						
							| 
									
										
										
										
											2022-08-11 23:56:43 +03:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	// a base page to be used as a base for cloning if root is of a 
 | 
					
						
							|  |  |  | 	// different "class"...
 | 
					
						
							| 
									
										
										
										
											2022-08-12 01:38:32 +03:00
										 |  |  | 	//__clone_proto__: undefined,
 | 
					
						
							| 
									
										
										
										
											2022-09-02 17:27:40 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-09-17 17:13:23 +03:00
										 |  |  | 	//
 | 
					
						
							|  |  |  | 	// Format:
 | 
					
						
							|  |  |  | 	// 	{
 | 
					
						
							|  |  |  | 	// 		<name>: true,
 | 
					
						
							|  |  |  | 	// 		<name>: <alias>,
 | 
					
						
							|  |  |  | 	// 	}
 | 
					
						
							|  |  |  | 	//
 | 
					
						
							|  |  |  | 	actions: {  | 
					
						
							|  |  |  | 		location: true, | 
					
						
							|  |  |  | 		referrer: true, | 
					
						
							|  |  |  | 		path: true, | 
					
						
							|  |  |  | 		name: true, | 
					
						
							|  |  |  | 		dir: true, | 
					
						
							|  |  |  | 		// alias...
 | 
					
						
							|  |  |  | 		args: 'argstr', | 
					
						
							|  |  |  | 		title: true, | 
					
						
							|  |  |  | 		resolved: true, | 
					
						
							|  |  |  | 		rootpath: true, | 
					
						
							|  |  |  | 		length: true, | 
					
						
							|  |  |  | 		type: true, | 
					
						
							|  |  |  | 		ctime: true, | 
					
						
							|  |  |  | 		mtime: true, | 
					
						
							| 
									
										
										
										
											2022-10-26 19:54:22 +03:00
										 |  |  | 		// XXX
 | 
					
						
							|  |  |  | 		//tags: true,
 | 
					
						
							| 
									
										
										
										
											2022-09-17 17:13:23 +03:00
										 |  |  | 	}, | 
					
						
							| 
									
										
										
										
											2022-09-17 13:26:49 +03:00
										 |  |  | 	// These actions will be default get :$ARGS appended if no args are 
 | 
					
						
							|  |  |  | 	// explicitly given...
 | 
					
						
							|  |  |  | 	// XXX INHERIT_ARGS
 | 
					
						
							|  |  |  | 	actions_inherit_args: new Set([ | 
					
						
							|  |  |  | 		'location', | 
					
						
							| 
									
										
										
										
											2022-09-17 17:13:23 +03:00
										 |  |  | 		'args', | 
					
						
							| 
									
										
										
										
											2022-09-17 13:26:49 +03:00
										 |  |  | 	]), | 
					
						
							| 
									
										
										
										
											2022-09-02 17:27:40 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-08-04 11:00:21 +03:00
										 |  |  | 	 | 
					
						
							| 
									
										
										
										
											2022-08-10 11:42:31 +03:00
										 |  |  | 	// NOTE: this can be inherited...
 | 
					
						
							|  |  |  | 	//store: undefined,
 | 
					
						
							|  |  |  | 	//__store: undefined,
 | 
					
						
							|  |  |  | 	get store(){ | 
					
						
							|  |  |  | 		return this.__store  | 
					
						
							|  |  |  | 			?? (this.root ?? {}).__store }, | 
					
						
							|  |  |  | 	set store(value){ | 
					
						
							|  |  |  | 		this.__store = value }, | 
					
						
							|  |  |  | 	 | 
					
						
							| 
									
										
										
										
											2022-08-04 11:00:21 +03:00
										 |  |  | 	// Path variables...
 | 
					
						
							|  |  |  | 	//
 | 
					
						
							|  |  |  | 	// XXX PATH_VARS should these be here???
 | 
					
						
							|  |  |  | 	// 		other places path variables can be resolved:
 | 
					
						
							|  |  |  | 	// 			- navigation (below)
 | 
					
						
							|  |  |  | 	// 			- macro expansion...
 | 
					
						
							|  |  |  | 	path_vars: { | 
					
						
							|  |  |  | 		NOW: function(){ | 
					
						
							| 
									
										
										
										
											2022-09-04 01:53:01 +03:00
										 |  |  | 			return Date.timeStamp() }, | 
					
						
							| 
									
										
										
										
											2022-08-04 11:00:21 +03:00
										 |  |  | 		PATH: function(){ | 
					
						
							|  |  |  | 			return this.path }, | 
					
						
							|  |  |  | 		NAME: function(){ | 
					
						
							|  |  |  | 			return this.name }, | 
					
						
							|  |  |  | 		DIR: function(){ | 
					
						
							|  |  |  | 			return this.dir }, | 
					
						
							| 
									
										
										
										
											2022-09-05 17:16:07 +03:00
										 |  |  | 		ARGS: function(){ | 
					
						
							|  |  |  | 			return pwpath.obj2args(this.args) }, | 
					
						
							| 
									
										
										
										
											2022-09-29 20:59:20 +03:00
										 |  |  | 		TITLE: function(){ | 
					
						
							|  |  |  | 			return this.title }, | 
					
						
							| 
									
										
										
										
											2022-08-04 11:00:21 +03:00
										 |  |  | 
 | 
					
						
							|  |  |  | 		/*/ XXX this needs: | 
					
						
							|  |  |  | 		// 		- macro context...
 | 
					
						
							|  |  |  | 		// 		- sort order...
 | 
					
						
							|  |  |  | 		INDEX: function(context){ | 
					
						
							|  |  |  | 			return context.index }, | 
					
						
							|  |  |  | 		//*/
 | 
					
						
							|  |  |  | 	}, | 
					
						
							| 
									
										
										
										
											2022-10-03 02:35:14 +03:00
										 |  |  | 	resolvePathVars: function(path='', context={}){ | 
					
						
							| 
									
										
										
										
											2022-08-04 11:00:21 +03:00
										 |  |  | 		var that = this | 
					
						
							| 
									
										
										
										
											2022-10-27 02:36:14 +03:00
										 |  |  | 		return path == '.' ? | 
					
						
							|  |  |  | 			path | 
					
						
							|  |  |  | 			: pwpath.normalize( | 
					
						
							|  |  |  | 				Object.entries(this.path_vars) | 
					
						
							|  |  |  | 					.reduce(function(res, [key, func]){ | 
					
						
							|  |  |  | 						return res | 
					
						
							|  |  |  | 							.replace( | 
					
						
							|  |  |  | 								new RegExp('(\\${'+key+'}|\\$'+key+')', 'g'),  | 
					
						
							|  |  |  | 								func.call(that, context)) | 
					
						
							|  |  |  | 					}, path)) }, | 
					
						
							| 
									
										
										
										
											2022-08-04 11:00:21 +03:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	// page location...
 | 
					
						
							|  |  |  | 	//
 | 
					
						
							|  |  |  | 	// NOTE: path variables are resolved relative to the page BEFORE 
 | 
					
						
							|  |  |  | 	// 		navigation...
 | 
					
						
							| 
									
										
										
										
											2022-10-28 14:10:31 +03:00
										 |  |  | 	// NOTE: the actual work is done by the .navigate(..) method...
 | 
					
						
							| 
									
										
										
										
											2022-08-04 11:00:21 +03:00
										 |  |  | 	__location: undefined, | 
					
						
							|  |  |  | 	get location(){ | 
					
						
							|  |  |  | 		return this.__location ?? '/' }, | 
					
						
							|  |  |  | 	set location(path){ | 
					
						
							|  |  |  | 		// trigger the event...
 | 
					
						
							| 
									
										
										
										
											2022-10-28 14:10:31 +03:00
										 |  |  | 		this.navigate(path) }, | 
					
						
							| 
									
										
										
										
											2022-08-04 11:00:21 +03:00
										 |  |  | 	// referrer -- a previous page location...
 | 
					
						
							|  |  |  | 	referrer: undefined, | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// events...
 | 
					
						
							|  |  |  | 	//
 | 
					
						
							| 
									
										
										
										
											2022-09-04 01:53:01 +03:00
										 |  |  | 	//__beforenavigate__: function(location){ .. },
 | 
					
						
							|  |  |  | 	//
 | 
					
						
							|  |  |  | 	//__navigate__: function(){ .. },
 | 
					
						
							|  |  |  | 	//
 | 
					
						
							| 
									
										
										
										
											2022-08-04 11:00:21 +03:00
										 |  |  | 	// XXX revise naming...
 | 
					
						
							|  |  |  | 	// XXX should this be able to prevent navigation???
 | 
					
						
							| 
									
										
										
										
											2022-10-28 14:10:31 +03:00
										 |  |  | 	onBeforeNavigate: types.event.PureEvent('beforeNavigate', | 
					
						
							| 
									
										
										
										
											2022-09-04 01:53:01 +03:00
										 |  |  | 		function(_, location){ | 
					
						
							|  |  |  | 			'__beforenavigate__' in this | 
					
						
							|  |  |  | 				&& this.__beforenavigate__(location) }), | 
					
						
							| 
									
										
										
										
											2022-10-28 14:10:31 +03:00
										 |  |  | 	navigate: types.event.Event('navigate', | 
					
						
							| 
									
										
										
										
											2022-09-01 00:04:13 +03:00
										 |  |  | 		function(handle, location){ | 
					
						
							| 
									
										
										
										
											2022-09-25 19:22:32 +03:00
										 |  |  | 			var {path, args} = pwpath.splitArgs(location) | 
					
						
							| 
									
										
										
										
											2022-10-28 14:10:31 +03:00
										 |  |  | 			this.trigger("onBeforeNavigate", location) | 
					
						
							| 
									
										
										
										
											2022-08-04 11:00:21 +03:00
										 |  |  | 			this.referrer = this.location | 
					
						
							|  |  |  | 			var cur = this.__location =  | 
					
						
							|  |  |  | 				this.resolvePathVars( | 
					
						
							| 
									
										
										
										
											2022-09-01 00:04:13 +03:00
										 |  |  | 					// NOTE: this is done instead of simply assigning 
 | 
					
						
							|  |  |  | 					// 		location as-is to normalize the paths and 
 | 
					
						
							|  |  |  | 					// 		arguments...
 | 
					
						
							|  |  |  | 					pwpath.joinArgs( | 
					
						
							|  |  |  | 						pwpath.relative( | 
					
						
							| 
									
										
										
										
											2022-11-01 23:58:50 +03:00
										 |  |  | 								this.path,  | 
					
						
							|  |  |  | 								path)  | 
					
						
							|  |  |  | 							// keep root path predictable...
 | 
					
						
							|  |  |  | 							|| '/', | 
					
						
							| 
									
										
										
										
											2022-09-01 00:04:13 +03:00
										 |  |  | 						pwpath.obj2args(args))) | 
					
						
							| 
									
										
										
										
											2022-08-04 11:00:21 +03:00
										 |  |  | 			// trigger handlers...
 | 
					
						
							| 
									
										
										
										
											2022-09-04 01:53:01 +03:00
										 |  |  | 			'__navigate__' in this | 
					
						
							|  |  |  | 				&& this.__navigate__() | 
					
						
							| 
									
										
										
										
											2022-08-04 11:00:21 +03:00
										 |  |  | 			handle() }), | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	get path(){ | 
					
						
							| 
									
										
										
										
											2022-08-31 15:46:51 +03:00
										 |  |  | 		return pwpath.splitArgs(this.location).path }, | 
					
						
							| 
									
										
										
										
											2022-08-04 11:00:21 +03:00
										 |  |  | 	set path(value){ | 
					
						
							|  |  |  | 		this.location = value }, | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-08-31 15:46:51 +03:00
										 |  |  | 	get args(){ | 
					
						
							|  |  |  | 		return pwpath.splitArgs(this.location).args }, | 
					
						
							|  |  |  | 	set args(args){ | 
					
						
							| 
									
										
										
										
											2022-09-05 17:16:07 +03:00
										 |  |  | 		args = pwpath.obj2args(args) ?? '' | 
					
						
							|  |  |  | 		this.location =  | 
					
						
							|  |  |  | 			args == '' ?  | 
					
						
							|  |  |  | 				'.' | 
					
						
							|  |  |  | 				: '.:'+ args }, | 
					
						
							| 
									
										
										
										
											2022-09-17 12:45:58 +03:00
										 |  |  | 	// helper...
 | 
					
						
							|  |  |  | 	get argstr(){ | 
					
						
							|  |  |  | 		return pwpath.obj2args(this.args) }, | 
					
						
							|  |  |  | 	set argstr(value){ | 
					
						
							|  |  |  | 		this.args = value }, | 
					
						
							| 
									
										
										
										
											2022-08-31 15:46:51 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-09-02 14:58:45 +03:00
										 |  |  | 	// NOTE: these are mostly here as helpers to be accessed via page 
 | 
					
						
							|  |  |  | 	// 		actions...
 | 
					
						
							|  |  |  | 	// XXX should these be here or in Page???
 | 
					
						
							|  |  |  | 	// XXX should this call .match(..) or .resolve(..)???
 | 
					
						
							|  |  |  | 	get resolved(){ | 
					
						
							|  |  |  | 		return this.resolve() }, | 
					
						
							|  |  |  | 	get rootpath(){ | 
					
						
							|  |  |  | 		return this.root ?  | 
					
						
							|  |  |  | 			this.root.path  | 
					
						
							|  |  |  | 			: this.path }, | 
					
						
							| 
									
										
										
										
											2022-08-04 11:00:21 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-09-21 23:37:52 +03:00
										 |  |  | 	// XXX should this encode/decode??? 
 | 
					
						
							| 
									
										
										
										
											2022-08-04 11:00:21 +03:00
										 |  |  | 	get name(){ | 
					
						
							| 
									
										
										
										
											2022-08-31 15:46:51 +03:00
										 |  |  | 		return pwpath.basename(this.path) }, | 
					
						
							| 
									
										
										
										
											2022-09-19 00:18:23 +03:00
										 |  |  | 	set name(value){ | 
					
						
							| 
									
										
										
										
											2022-09-25 19:22:32 +03:00
										 |  |  | 		if(pwpath.normalize(value) == ''){ | 
					
						
							|  |  |  | 			return } | 
					
						
							| 
									
										
										
										
											2022-09-19 00:18:23 +03:00
										 |  |  | 		this.move( | 
					
						
							|  |  |  | 			/^[\\\/]/.test(value) ? | 
					
						
							|  |  |  | 				value | 
					
						
							|  |  |  | 				: '../'+value) }, | 
					
						
							| 
									
										
										
										
											2022-08-04 11:00:21 +03:00
										 |  |  | 	get dir(){ | 
					
						
							| 
									
										
										
										
											2022-08-31 15:46:51 +03:00
										 |  |  | 		return pwpath.dirname(this.path) }, | 
					
						
							| 
									
										
										
										
											2022-09-19 00:18:23 +03:00
										 |  |  | 	set dir(value){  | 
					
						
							|  |  |  | 		var to = pwpath.join(value, this.name) | 
					
						
							|  |  |  | 		this.move( | 
					
						
							|  |  |  | 			/^[\\\/]/.test(to) ? | 
					
						
							|  |  |  | 				to | 
					
						
							|  |  |  | 				: '../'+to) }, | 
					
						
							| 
									
										
										
										
											2022-09-02 22:09:51 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-09-22 02:52:14 +03:00
										 |  |  | 	get title(){ | 
					
						
							|  |  |  | 		return pwpath.decodeElem(this.name) }, | 
					
						
							|  |  |  | 	set title(value){ | 
					
						
							|  |  |  | 		this.name = pwpath.encodeElem(value) }, | 
					
						
							| 
									
										
										
										
											2022-09-02 22:09:51 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-08-04 11:00:21 +03:00
										 |  |  | 	get isPattern(){ | 
					
						
							| 
									
										
										
										
											2022-08-31 15:46:51 +03:00
										 |  |  | 		return this.path.includes('*') }, | 
					
						
							| 
									
										
										
										
											2022-09-02 17:27:40 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-02-15 02:33:20 +03:00
										 |  |  | 	// XXX EXPERIMENTAL...
 | 
					
						
							|  |  |  | 	get ctime(){ | 
					
						
							|  |  |  | 		var that = this | 
					
						
							|  |  |  | 		return Promise.awaitOrRun( | 
					
						
							|  |  |  | 			this.data, | 
					
						
							|  |  |  | 			function(data){ | 
					
						
							|  |  |  | 				var t = (data ?? {}).ctime | 
					
						
							|  |  |  | 				return t ? | 
					
						
							|  |  |  | 					new Date(t).getTimeStamp() | 
					
						
							|  |  |  | 					: t }) }, | 
					
						
							|  |  |  | 	get mtime(){ | 
					
						
							|  |  |  | 		var that = this | 
					
						
							|  |  |  | 		return Promise.awaitOrRun( | 
					
						
							|  |  |  | 			this.data, | 
					
						
							|  |  |  | 			function(data){ | 
					
						
							|  |  |  | 				var t = (data ?? {}).mtime | 
					
						
							|  |  |  | 				return t ? | 
					
						
							|  |  |  | 					new Date(t).getTimeStamp() | 
					
						
							|  |  |  | 					: t }) }, | 
					
						
							|  |  |  | 	/*/ // XXX ASYNC...
 | 
					
						
							| 
									
										
										
										
											2022-09-02 17:27:40 +03:00
										 |  |  | 	get ctime(){ return async function(){ | 
					
						
							|  |  |  | 		var t = ((await this.data) ?? {}).ctime | 
					
						
							|  |  |  | 		return t ? | 
					
						
							|  |  |  | 			new Date(t).getTimeStamp() | 
					
						
							|  |  |  | 			: t }.call(this) }, | 
					
						
							|  |  |  | 	get mtime(){ return async function(){ | 
					
						
							|  |  |  | 		var t = ((await this.data) ?? {}).mtime | 
					
						
							|  |  |  | 		return t ? | 
					
						
							|  |  |  | 			new Date(t).getTimeStamp() | 
					
						
							|  |  |  | 			: t }.call(this) }, | 
					
						
							| 
									
										
										
										
											2023-02-15 02:33:20 +03:00
										 |  |  | 	//*/
 | 
					
						
							| 
									
										
										
										
											2022-08-04 11:00:21 +03:00
										 |  |  | 	 | 
					
						
							|  |  |  | 	// store interface...
 | 
					
						
							|  |  |  | 	//
 | 
					
						
							|  |  |  | 	// XXX we are only doing modifiers here...
 | 
					
						
							|  |  |  | 	// 		...these ar mainly used to disable writing in .ro(..)
 | 
					
						
							|  |  |  | 	__update__: function(data){ | 
					
						
							| 
									
										
										
										
											2022-08-31 15:46:51 +03:00
										 |  |  | 		return this.store.update(this.path, data) }, | 
					
						
							| 
									
										
										
										
											2022-08-04 11:00:21 +03:00
										 |  |  | 	__delete__: function(path='.'){ | 
					
						
							| 
									
										
										
										
											2022-08-31 15:46:51 +03:00
										 |  |  | 		return this.store.delete(pwpath.relative(this.path, path)) }, | 
					
						
							| 
									
										
										
										
											2022-08-04 11:00:21 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-09-02 17:27:40 +03:00
										 |  |  | 	__energetic: undefined, | 
					
						
							| 
									
										
										
										
											2023-02-11 23:12:51 +03:00
										 |  |  | 	get energetic(){ | 
					
						
							|  |  |  | 		return this.__energetic === true | 
					
						
							|  |  |  | 			|| ((this.actions  | 
					
						
							|  |  |  | 				&& this.actions[this.name] | 
					
						
							|  |  |  | 				&& !!this[ | 
					
						
							|  |  |  | 					this.actions[this.name] === true ? | 
					
						
							|  |  |  | 						this.name | 
					
						
							|  |  |  | 						: this.actions[this.name] ].energetic) | 
					
						
							|  |  |  | 			|| Promise.awaitOrRun( | 
					
						
							|  |  |  | 				this.store.isEnergetic(this.path), | 
					
						
							|  |  |  | 		   		function(res){ | 
					
						
							|  |  |  | 					return !!res })) }, | 
					
						
							| 
									
										
										
										
											2022-09-02 17:27:40 +03:00
										 |  |  | 	set energetic(value){ | 
					
						
							|  |  |  | 		this.__energetic = value }, | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-08-04 11:00:21 +03:00
										 |  |  | 	// page data...
 | 
					
						
							|  |  |  | 	//
 | 
					
						
							|  |  |  | 	strict: undefined, | 
					
						
							| 
									
										
										
										
											2023-02-11 23:12:51 +03:00
										 |  |  | 	get data(){ | 
					
						
							|  |  |  | 		var that = this | 
					
						
							|  |  |  | 		// direct actions...
 | 
					
						
							|  |  |  | 		if(this.actions  | 
					
						
							|  |  |  | 				&& this.actions[this.name]){ | 
					
						
							|  |  |  | 			var name =  | 
					
						
							|  |  |  | 				this.actions[this.name] === true ? | 
					
						
							|  |  |  | 					this.name | 
					
						
							|  |  |  | 					: this.actions[this.name] | 
					
						
							|  |  |  | 			var args = this.args | 
					
						
							|  |  |  | 			var page = this.get('..', {args}) | 
					
						
							|  |  |  | 			return Promise.awaitOrRun( | 
					
						
							|  |  |  | 				(this.isPattern  | 
					
						
							|  |  |  | 						&& !this.__energetic | 
					
						
							|  |  |  | 						&& !page[name].energetic) ? | 
					
						
							|  |  |  | 					page | 
					
						
							|  |  |  | 						.map(function(page){ | 
					
						
							|  |  |  | 							var res = page[name]  | 
					
						
							|  |  |  | 							return typeof(res) == 'function' ? | 
					
						
							|  |  |  | 								res.bind(page.get(name, {args})) | 
					
						
							|  |  |  | 								: function(){  | 
					
						
							|  |  |  | 									return res } }) | 
					
						
							|  |  |  | 					: page[name], | 
					
						
							|  |  |  | 				function(res){ | 
					
						
							|  |  |  | 					return typeof(res) == 'function' ? | 
					
						
							|  |  |  | 							res.bind(that) | 
					
						
							|  |  |  | 						: res instanceof Array ? | 
					
						
							|  |  |  | 							res | 
					
						
							|  |  |  | 						: function(){  | 
					
						
							|  |  |  | 							return res } }, | 
					
						
							|  |  |  | 				// NOTE: we are passing null into the error handler to 
 | 
					
						
							|  |  |  | 				// 		prevent the actual data (function) from being 
 | 
					
						
							|  |  |  | 				// 		consumed...
 | 
					
						
							|  |  |  | 				null) } | 
					
						
							|  |  |  | 		// store data...
 | 
					
						
							|  |  |  | 		return Promise.awaitOrRun( | 
					
						
							|  |  |  | 			this.energetic, | 
					
						
							|  |  |  | 			function(energetic){ | 
					
						
							|  |  |  | 				// pattern...
 | 
					
						
							|  |  |  | 				// NOTE: we need to make sure each page gets the chance to handle 
 | 
					
						
							|  |  |  | 				// 		its context (i.e. bind action to page)....
 | 
					
						
							|  |  |  | 				if(that.isPattern | 
					
						
							|  |  |  | 						&& !energetic){ | 
					
						
							|  |  |  | 					return that | 
					
						
							|  |  |  | 						.map(function(page){ | 
					
						
							|  |  |  | 							return page.data }) } | 
					
						
							|  |  |  | 				// single page...
 | 
					
						
							|  |  |  | 				return Promise.awaitOrRun( | 
					
						
							|  |  |  | 					that.store.get(that.path, !!that.strict, !!energetic), | 
					
						
							|  |  |  | 					function(res){ | 
					
						
							|  |  |  | 						return typeof(res) == 'function' ? | 
					
						
							|  |  |  | 							res.bind(that) | 
					
						
							|  |  |  | 							: res }) }) }, | 
					
						
							| 
									
										
										
										
											2022-08-04 11:00:21 +03:00
										 |  |  | 	set data(value){ | 
					
						
							| 
									
										
										
										
											2022-09-19 00:18:23 +03:00
										 |  |  | 		if(this.actions  | 
					
						
							|  |  |  | 				&& this.actions[this.name]){ | 
					
						
							|  |  |  | 			var name =  | 
					
						
							|  |  |  | 				this.actions[this.name] === true ? | 
					
						
							|  |  |  | 					this.name | 
					
						
							|  |  |  | 					: this.actions[this.name] | 
					
						
							|  |  |  | 			var page = this.get('..') | 
					
						
							|  |  |  | 			// NOTE: this can return a promise, as we'll need to assign 
 | 
					
						
							|  |  |  | 			// 		we do not care about it as long as it's not a function...
 | 
					
						
							|  |  |  | 			// 		XXX not sure if this is a good idea...
 | 
					
						
							|  |  |  | 			var res = page[name] | 
					
						
							|  |  |  | 			// set...
 | 
					
						
							|  |  |  | 			typeof(res) == 'function' ? | 
					
						
							|  |  |  | 				page[name](value.text ?? value) | 
					
						
							|  |  |  | 			: (page[name] = value.text ?? value) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		// normal update...
 | 
					
						
							|  |  |  | 		} else { | 
					
						
							|  |  |  | 			this.__update__(value) } }, | 
					
						
							| 
									
										
										
										
											2022-08-04 11:00:21 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-10-26 17:17:06 +03:00
										 |  |  | 	// tags...
 | 
					
						
							|  |  |  | 	//
 | 
					
						
							| 
									
										
										
										
											2022-10-26 19:18:21 +03:00
										 |  |  | 	/* | 
					
						
							| 
									
										
										
										
											2022-10-26 17:06:06 +03:00
										 |  |  | 	get tags(){ return async function(){ | 
					
						
							|  |  |  | 		return (await this.data).tags ?? [] }.call(this) }, | 
					
						
							| 
									
										
										
										
											2022-10-26 19:18:21 +03:00
										 |  |  | 	/*/ | 
					
						
							|  |  |  | 	get tags(){ | 
					
						
							|  |  |  | 		var tags = this.store.tags | 
					
						
							|  |  |  | 		var path = pwpath.sanitize(this.path) | 
					
						
							|  |  |  | 		return tags instanceof Promise ? | 
					
						
							|  |  |  | 			tags.then(function(tags){ | 
					
						
							|  |  |  | 				return tags.paths[path] ?? [] }) | 
					
						
							|  |  |  | 			: this.store.tags.paths[path] ?? [] }, | 
					
						
							|  |  |  | 	//*/
 | 
					
						
							| 
									
										
										
										
											2022-10-26 17:06:06 +03:00
										 |  |  | 	set tags(value){ return async function(){ | 
					
						
							|  |  |  | 		this.data = { | 
					
						
							|  |  |  | 			...(await this.data), | 
					
						
							|  |  |  | 			tags: [...value], | 
					
						
							|  |  |  | 		} }.call(this) }, | 
					
						
							|  |  |  | 	tag: async function(...tags){ | 
					
						
							|  |  |  | 		this.tags = [...new Set([ | 
					
						
							|  |  |  | 			...(await this.tags),  | 
					
						
							|  |  |  | 			...tags, | 
					
						
							|  |  |  | 		])] | 
					
						
							|  |  |  | 		return this }, | 
					
						
							|  |  |  | 	untag: async function(...tags){ | 
					
						
							|  |  |  | 		this.tags = (await this.tags) | 
					
						
							|  |  |  | 			.filter(function(tag){ | 
					
						
							|  |  |  | 				return !tags.includes(tag) }) | 
					
						
							|  |  |  | 		return this }, | 
					
						
							| 
									
										
										
										
											2022-10-26 17:17:06 +03:00
										 |  |  | 	toggleTags: async function(...tags){ | 
					
						
							|  |  |  | 		var t = new Set(await this.tags) | 
					
						
							|  |  |  | 		for(var tag of tags){ | 
					
						
							|  |  |  | 			t.has(tag) ? | 
					
						
							|  |  |  | 				t.delete(tag) | 
					
						
							|  |  |  | 				: t.add(tag) } | 
					
						
							|  |  |  | 		this.tags = t | 
					
						
							|  |  |  | 		return this }, | 
					
						
							| 
									
										
										
										
											2022-10-26 17:06:06 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-08-04 11:00:21 +03:00
										 |  |  | 	// metadata...
 | 
					
						
							|  |  |  | 	//
 | 
					
						
							|  |  |  | 	// NOTE: in the general case this is the same as .data but in also allows
 | 
					
						
							|  |  |  | 	// 		storing of data (metadata) for pattern paths...
 | 
					
						
							|  |  |  | 	get metadata(){ | 
					
						
							| 
									
										
										
										
											2022-08-31 15:46:51 +03:00
										 |  |  | 		return this.store.metadata(this.path) }, | 
					
						
							| 
									
										
										
										
											2022-08-04 11:00:21 +03:00
										 |  |  | 	set metadata(value){ | 
					
						
							| 
									
										
										
										
											2022-11-25 01:23:16 +03:00
										 |  |  | 		// clear...
 | 
					
						
							|  |  |  | 		if(arguments.length > 0  | 
					
						
							|  |  |  | 				&& value == null){ | 
					
						
							|  |  |  | 			return this.__delete__() } | 
					
						
							|  |  |  | 		// set...
 | 
					
						
							| 
									
										
										
										
											2022-08-04 11:00:21 +03:00
										 |  |  | 		this.__update__(value) }, | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-02-11 23:12:51 +03:00
										 |  |  | 	// XXX ASYNC???
 | 
					
						
							| 
									
										
										
										
											2022-08-21 23:07:47 +03:00
										 |  |  | 	get type(){ return async function(){ | 
					
						
							|  |  |  | 		return this.store.isStore(this.path) ? | 
					
						
							|  |  |  | 				'store' | 
					
						
							|  |  |  | 			: typeof(await this.data) == 'function' ?  | 
					
						
							|  |  |  | 				'action'  | 
					
						
							|  |  |  | 			: 'page' }.bind(this)() }, | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-08-04 11:00:21 +03:00
										 |  |  | 	// number of matching pages...
 | 
					
						
							|  |  |  | 	// NOTE: this can be both sync and async...
 | 
					
						
							|  |  |  | 	get length(){ | 
					
						
							| 
									
										
										
										
											2022-10-03 15:17:11 +03:00
										 |  |  | 		var p = this.resolve(this.location) | 
					
						
							| 
									
										
										
										
											2022-08-04 11:00:21 +03:00
										 |  |  | 		return p instanceof Array ? | 
					
						
							|  |  |  | 				p.length | 
					
						
							|  |  |  | 			: p instanceof Promise ? | 
					
						
							|  |  |  | 				p.then(function(res){ | 
					
						
							|  |  |  | 					return res instanceof Array ? | 
					
						
							|  |  |  | 						res.length | 
					
						
							|  |  |  | 						: 1 }) | 
					
						
							|  |  |  | 			: 1 }, | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// relative proxies to store...
 | 
					
						
							|  |  |  | 	exists: relProxy('exists'),  | 
					
						
							| 
									
										
										
										
											2023-02-15 02:33:20 +03:00
										 |  |  | 	// XXX which match should we use???
 | 
					
						
							|  |  |  | 	//match: relMatchProxy('match'), 
 | 
					
						
							|  |  |  | 	match: function(path='.', strict=false){ | 
					
						
							|  |  |  | 		var that = this | 
					
						
							|  |  |  | 		if(path === true || path === false){ | 
					
						
							|  |  |  | 			strict = path | 
					
						
							|  |  |  | 			path = '.' } | 
					
						
							|  |  |  | 		path = pwpath.relative(this.path, path) | 
					
						
							|  |  |  | 		return Promise.awaitOrRun( | 
					
						
							|  |  |  | 			this.store.match(path, strict), | 
					
						
							|  |  |  | 			function(res){ | 
					
						
							|  |  |  | 				return res.length == 0 ? | 
					
						
							|  |  |  | 					// XXX are we going outside of match semantics here???
 | 
					
						
							|  |  |  | 					that.store.find(path)  | 
					
						
							|  |  |  | 					: res }) }, | 
					
						
							|  |  |  | 	/*/ // XXX ASYNC...
 | 
					
						
							| 
									
										
										
										
											2022-08-14 23:54:02 +03:00
										 |  |  | 	match: async function(path='.', strict=false){ | 
					
						
							|  |  |  | 		if(path === true || path === false){ | 
					
						
							|  |  |  | 			strict = path | 
					
						
							|  |  |  | 			path = '.' } | 
					
						
							| 
									
										
										
										
											2022-08-31 15:46:51 +03:00
										 |  |  | 		path = pwpath.relative(this.path, path) | 
					
						
							| 
									
										
										
										
											2022-08-14 23:54:02 +03:00
										 |  |  | 		var res = await this.store.match(path, strict)  | 
					
						
							|  |  |  | 		return res.length == 0 ? | 
					
						
							|  |  |  | 			// XXX are we going outside of match semantics here???
 | 
					
						
							|  |  |  | 			this.store.find(path)  | 
					
						
							|  |  |  | 			: res }, | 
					
						
							|  |  |  | 	//*/
 | 
					
						
							| 
									
										
										
										
											2022-08-04 11:00:21 +03:00
										 |  |  | 	resolve: relMatchProxy('resolve'), | 
					
						
							| 
									
										
										
										
											2022-08-15 17:32:07 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-10-31 02:29:21 +03:00
										 |  |  | 	delete: types.event.Event('delete',  | 
					
						
							|  |  |  | 		async function(handle, path='.', base=true){ | 
					
						
							|  |  |  | 			handle(false) | 
					
						
							|  |  |  | 			if(path === true || path === false){ | 
					
						
							|  |  |  | 				base = path | 
					
						
							|  |  |  | 				path = '.'	} | 
					
						
							|  |  |  | 			var page = this.get(path) | 
					
						
							|  |  |  | 			if(page.isPattern){ | 
					
						
							|  |  |  | 				base | 
					
						
							|  |  |  | 					&& this.__delete__(this.path.split('*')[0]) | 
					
						
							|  |  |  | 				for(var p of await this.get('path').raw){ | 
					
						
							|  |  |  | 					this.__delete__(p) } | 
					
						
							|  |  |  | 			} else { | 
					
						
							|  |  |  | 				this.__delete__(path) } | 
					
						
							|  |  |  | 			handle() | 
					
						
							|  |  |  | 			return this }), | 
					
						
							| 
									
										
										
										
											2022-08-15 17:32:07 +03:00
										 |  |  | 	// XXX should these be implemented here or proxy to .store???
 | 
					
						
							| 
									
										
										
										
											2022-09-24 01:02:01 +03:00
										 |  |  | 	// XXX do we sanity check to no not contain '*'???
 | 
					
						
							|  |  |  | 	copy: async function(to, base=true){ | 
					
						
							| 
									
										
										
										
											2022-09-25 19:22:32 +03:00
										 |  |  | 		if(this.get(to).path == this.path){ | 
					
						
							|  |  |  | 			return this } | 
					
						
							| 
									
										
										
										
											2022-09-24 01:02:01 +03:00
										 |  |  | 		// copy children...
 | 
					
						
							|  |  |  | 		if(this.isPattern){ | 
					
						
							|  |  |  | 			var base = this.path.split('*')[0] | 
					
						
							|  |  |  | 			// copy the base...
 | 
					
						
							|  |  |  | 			base  | 
					
						
							|  |  |  | 				&& (this.get(to).data = await this.get(base).data) | 
					
						
							|  |  |  | 			for(var from of await this.get('path').raw){  | 
					
						
							|  |  |  | 				this.get(pwpath.join(to, from.slice(base.length))).data =  | 
					
						
							|  |  |  | 					await this.get(from).data } | 
					
						
							|  |  |  | 		// copy self...
 | 
					
						
							|  |  |  | 		} else { | 
					
						
							|  |  |  | 			this.get(to).data = await this.data } | 
					
						
							|  |  |  | 		// change location...
 | 
					
						
							| 
									
										
										
										
											2022-08-15 17:32:07 +03:00
										 |  |  | 		this.path = to | 
					
						
							|  |  |  | 		return this }, | 
					
						
							| 
									
										
										
										
											2022-09-24 01:02:01 +03:00
										 |  |  | 	move: async function(to, base=true){ | 
					
						
							| 
									
										
										
										
											2022-08-15 17:32:07 +03:00
										 |  |  | 		var from = this.path | 
					
						
							| 
									
										
										
										
											2022-09-25 19:22:32 +03:00
										 |  |  | 		if(this.get(to).path == this.path){ | 
					
						
							|  |  |  | 			return this } | 
					
						
							| 
									
										
										
										
											2022-09-24 01:02:01 +03:00
										 |  |  | 		await this.copy(to, base) | 
					
						
							|  |  |  | 		this.delete(from, base) | 
					
						
							| 
									
										
										
										
											2022-08-04 11:00:21 +03:00
										 |  |  | 		return this }, | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-09-24 01:02:01 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-08-05 12:46:00 +03:00
										 |  |  | 	//
 | 
					
						
							|  |  |  | 	// 	Find current path (non-strict)
 | 
					
						
							|  |  |  | 	// 	.find()
 | 
					
						
							|  |  |  | 	// 	.find(false)
 | 
					
						
							|  |  |  | 	// 	.find('.')
 | 
					
						
							|  |  |  | 	// 	.find('.', false)
 | 
					
						
							|  |  |  | 	// 		-> path
 | 
					
						
							|  |  |  | 	// 		-> undefined
 | 
					
						
							|  |  |  | 	//
 | 
					
						
							|  |  |  | 	// 	Find current path in strict/non-strict mode...
 | 
					
						
							|  |  |  | 	// 	.find(true)
 | 
					
						
							|  |  |  | 	// 	.find(false)
 | 
					
						
							|  |  |  | 	// 		-> path
 | 
					
						
							|  |  |  | 	// 		-> undefined
 | 
					
						
							|  |  |  | 	//
 | 
					
						
							|  |  |  | 	// 	Find path relative to current page (strict/non-strict)
 | 
					
						
							|  |  |  | 	// 	.find(<path>[, <strict>])
 | 
					
						
							|  |  |  | 	// 		-> path
 | 
					
						
							|  |  |  | 	// 		-> undefined
 | 
					
						
							|  |  |  | 	//
 | 
					
						
							| 
									
										
										
										
											2022-09-07 16:37:26 +03:00
										 |  |  | 	// XXX ARGS preserve args...
 | 
					
						
							| 
									
										
										
										
											2022-08-05 12:46:00 +03:00
										 |  |  | 	find: function(path='.', strict=false){ | 
					
						
							|  |  |  | 		if(path === true || path === false){ | 
					
						
							|  |  |  | 			strict = path | 
					
						
							|  |  |  | 			path = '.' } | 
					
						
							|  |  |  | 		return this.store.find( | 
					
						
							| 
									
										
										
										
											2022-08-31 15:46:51 +03:00
										 |  |  | 			pwpath.relative(this.path, path), strict) }, | 
					
						
							| 
									
										
										
										
											2022-08-05 12:46:00 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-08-04 11:00:21 +03:00
										 |  |  | 	//
 | 
					
						
							|  |  |  | 	// 	.get(<path>[, <data>])
 | 
					
						
							|  |  |  | 	// 	.get(<path>, <strict>[, <data>])
 | 
					
						
							|  |  |  | 	// 		-> <page>
 | 
					
						
							|  |  |  | 	//
 | 
					
						
							|  |  |  | 	get: function(path, strict, data={}){ | 
					
						
							|  |  |  | 		if(strict instanceof Object){ | 
					
						
							|  |  |  | 			data = strict | 
					
						
							|  |  |  | 			strict = undefined } | 
					
						
							|  |  |  | 		return this.clone({ | 
					
						
							|  |  |  | 				location: path,  | 
					
						
							|  |  |  | 				...data, | 
					
						
							|  |  |  | 				referrer: data.referrer  | 
					
						
							| 
									
										
										
										
											2022-08-31 15:46:51 +03:00
										 |  |  | 					//?? this.path,
 | 
					
						
							| 
									
										
										
										
											2022-08-15 14:29:45 +03:00
										 |  |  | 					?? this.referrer, | 
					
						
							| 
									
										
										
										
											2022-08-04 11:00:21 +03:00
										 |  |  | 				strict, | 
					
						
							|  |  |  | 			}) }, | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// XXX should this be an iterator???
 | 
					
						
							| 
									
										
										
										
											2023-02-19 15:02:44 +03:00
										 |  |  | 	each: function(path, strict){ | 
					
						
							| 
									
										
										
										
											2023-02-14 16:50:35 +03:00
										 |  |  | 		var that = this | 
					
						
							| 
									
										
										
										
											2023-02-19 15:02:44 +03:00
										 |  |  | 		if(path === true || path === false){ | 
					
						
							|  |  |  | 			strict = path | 
					
						
							|  |  |  | 			path = null } | 
					
						
							|  |  |  | 		strict = strict  | 
					
						
							|  |  |  | 			?? this.strict | 
					
						
							| 
									
										
										
										
											2023-02-14 16:50:35 +03:00
										 |  |  | 		// NOTE: we are trying to avoid resolving non-pattern paths unless 
 | 
					
						
							|  |  |  | 		// 		we really have to...
 | 
					
						
							|  |  |  | 		path = path ? | 
					
						
							|  |  |  | 			pwpath.relative(this.path, path) | 
					
						
							|  |  |  | 			: this.location | 
					
						
							|  |  |  | 		var paths = path.includes('*') ? | 
					
						
							|  |  |  | 			Promise.awaitOrRun( | 
					
						
							|  |  |  | 				this.energetic, | 
					
						
							|  |  |  | 				this.store.isEnergetic(path), | 
					
						
							|  |  |  | 				function(a, b){ | 
					
						
							|  |  |  | 					return !(a || b) ? | 
					
						
							|  |  |  | 						that.resolve(path) | 
					
						
							|  |  |  | 						: path }) | 
					
						
							|  |  |  | 			: path | 
					
						
							|  |  |  | 		paths = Promise.awaitOrRun( | 
					
						
							|  |  |  | 			paths, | 
					
						
							|  |  |  | 			function(paths){ | 
					
						
							|  |  |  | 				return (paths instanceof Array  | 
					
						
							|  |  |  | 							|| paths instanceof Promise) ? | 
					
						
							|  |  |  | 						paths | 
					
						
							|  |  |  | 					: [paths] }) | 
					
						
							|  |  |  | 		return Promise.iter( | 
					
						
							|  |  |  | 			paths, | 
					
						
							|  |  |  | 			function(path){ | 
					
						
							| 
									
										
										
										
											2023-02-19 15:02:44 +03:00
										 |  |  | 				return strict ? | 
					
						
							|  |  |  | 					Promise.awaitOrRun( | 
					
						
							|  |  |  | 						that.exists('/'+path), | 
					
						
							|  |  |  | 						function(exists){ | 
					
						
							|  |  |  | 							return exists ? | 
					
						
							|  |  |  | 								that.get('/'+ path) | 
					
						
							|  |  |  | 								: [] }) | 
					
						
							|  |  |  | 					: that.get('/'+ path) }) | 
					
						
							| 
									
										
										
										
											2023-02-14 16:50:35 +03:00
										 |  |  | 			.sync() }, | 
					
						
							| 
									
										
										
										
											2023-02-15 02:33:20 +03:00
										 |  |  | 	// XXX is this correct here???
 | 
					
						
							| 
									
										
										
										
											2022-08-19 19:40:28 +03:00
										 |  |  | 	[Symbol.asyncIterator]: async function*(){ | 
					
						
							|  |  |  | 		yield* this.each() }, | 
					
						
							| 
									
										
										
										
											2022-08-05 12:46:00 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-02-14 16:50:35 +03:00
										 |  |  | 	map: function(func){ | 
					
						
							| 
									
										
										
										
											2022-08-04 11:00:21 +03:00
										 |  |  | 		return this.each().map(func) }, | 
					
						
							| 
									
										
										
										
											2023-02-14 16:50:35 +03:00
										 |  |  | 	filter: function(func){ | 
					
						
							| 
									
										
										
										
											2022-08-04 11:00:21 +03:00
										 |  |  | 		return this.each().filter(func) }, | 
					
						
							| 
									
										
										
										
											2023-02-14 16:50:35 +03:00
										 |  |  | 	reduce: function(func, dfl){ | 
					
						
							| 
									
										
										
										
											2022-08-04 11:00:21 +03:00
										 |  |  | 		return this.each().reduce(func, dfl) }, | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// sorting...
 | 
					
						
							|  |  |  | 	//
 | 
					
						
							| 
									
										
										
										
											2022-11-24 11:56:06 +03:00
										 |  |  | 	// XXX revise how we sore order...
 | 
					
						
							| 
									
										
										
										
											2022-11-23 20:12:39 +03:00
										 |  |  | 	sort: async function(...cmp){ | 
					
						
							|  |  |  | 		// normalize to path...
 | 
					
						
							| 
									
										
										
										
											2022-08-05 12:46:00 +03:00
										 |  |  | 		this.metadata =  | 
					
						
							| 
									
										
										
										
											2022-11-23 20:12:39 +03:00
										 |  |  | 			{ order: await this.store.sort(this.path, ...cmp) } | 
					
						
							| 
									
										
										
										
											2022-08-04 11:00:21 +03:00
										 |  |  | 		return this }, | 
					
						
							| 
									
										
										
										
											2022-11-24 01:14:38 +03:00
										 |  |  | 	//	.sortAs(<name>)
 | 
					
						
							|  |  |  | 	//	.sortAs([<path>, .. ])
 | 
					
						
							|  |  |  | 	sortAs: async function(order){ | 
					
						
							|  |  |  | 		this.metadata =  | 
					
						
							|  |  |  | 			order instanceof Array ? | 
					
						
							| 
									
										
										
										
											2022-11-24 11:56:06 +03:00
										 |  |  | 				{ order: order | 
					
						
							|  |  |  | 					.map(function(p){  | 
					
						
							|  |  |  | 						return pwpath.sanitize(p) }) } | 
					
						
							| 
									
										
										
										
											2022-11-24 01:14:38 +03:00
										 |  |  | 				: { order: (await this.metadata)['order_'+ order] } | 
					
						
							|  |  |  | 		return this }, | 
					
						
							|  |  |  | 	//	.saveSortAs(<name>)
 | 
					
						
							|  |  |  | 	//	.saveSortAs(<name>, [<path>, .. ])
 | 
					
						
							|  |  |  | 	saveSortAs: async function(name, order=null){ | 
					
						
							|  |  |  | 		order = order  | 
					
						
							|  |  |  | 			?? (await this.metadata).order | 
					
						
							|  |  |  | 		this.metadata = {['order_'+ name]: order} | 
					
						
							|  |  |  | 		return this }, | 
					
						
							| 
									
										
										
										
											2022-08-04 11:00:21 +03:00
										 |  |  | 	reverse: async function(){ | 
					
						
							|  |  |  | 		// not sorting single pages...
 | 
					
						
							|  |  |  | 		if(this.length <= 1){ | 
					
						
							|  |  |  | 			return this } | 
					
						
							| 
									
										
										
										
											2022-11-23 20:12:39 +03:00
										 |  |  | 		this.sort('reverse') | 
					
						
							| 
									
										
										
										
											2022-08-04 11:00:21 +03:00
										 |  |  | 		return this }, | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	//
 | 
					
						
							|  |  |  | 	// 	Clone a page optionally asigning data into it...
 | 
					
						
							|  |  |  | 	// 	.clone()
 | 
					
						
							|  |  |  | 	// 	.clone({ .. }[, <clone-history>])
 | 
					
						
							|  |  |  | 	// 		-> <page>
 | 
					
						
							|  |  |  | 	//
 | 
					
						
							|  |  |  | 	// 	Fully clone a page optionally asigning data into it...
 | 
					
						
							|  |  |  | 	// 	.clone(true[, <clone-history>])
 | 
					
						
							|  |  |  | 	// 	.clone(true, { .. }[, <clone-history>])
 | 
					
						
							|  |  |  | 	// 		-> <page>
 | 
					
						
							|  |  |  | 	//
 | 
					
						
							|  |  |  | 	//
 | 
					
						
							|  |  |  | 	// Normal cloning will inherit all the "clones" from the original 
 | 
					
						
							|  |  |  | 	// page overloading .location and .referrer
 | 
					
						
							|  |  |  | 	//
 | 
					
						
							|  |  |  | 	// NOTE: <clone-history> by default is false unless fully cloning
 | 
					
						
							|  |  |  | 	//
 | 
					
						
							|  |  |  | 	clone: function(data={}, history=false){ | 
					
						
							|  |  |  | 		var [data, ...args] = [...arguments] | 
					
						
							|  |  |  | 		var full = data === true | 
					
						
							|  |  |  | 		history =  | 
					
						
							|  |  |  | 			typeof(args[args.length-1]) == 'boolean' ?  | 
					
						
							|  |  |  | 				args.pop()  | 
					
						
							|  |  |  | 				: full | 
					
						
							|  |  |  | 		data = full ?  | 
					
						
							|  |  |  | 			args[0] ?? {}  | 
					
						
							|  |  |  | 			: data | 
					
						
							| 
									
										
										
										
											2022-08-12 01:38:32 +03:00
										 |  |  | 		var src = this.__clone_proto__  | 
					
						
							|  |  |  | 			?? (this.root || {}).__clone_proto__ | 
					
						
							|  |  |  | 			?? this.root | 
					
						
							|  |  |  | 			?? this | 
					
						
							| 
									
										
										
										
											2022-08-04 11:00:21 +03:00
										 |  |  | 		return Object.assign( | 
					
						
							|  |  |  | 			full ? | 
					
						
							|  |  |  | 				// full copy...
 | 
					
						
							| 
									
										
										
										
											2022-08-12 01:38:32 +03:00
										 |  |  | 				// XXX src or this???
 | 
					
						
							|  |  |  | 				//this.constructor(this.path, this.referrer, this.store)
 | 
					
						
							|  |  |  | 				src.constructor(this.path, this.referrer, this.store) | 
					
						
							| 
									
										
										
										
											2022-08-04 11:00:21 +03:00
										 |  |  | 				// NOTE: this will restrict all the clones to the first 
 | 
					
						
							|  |  |  | 				// 		generation maintaining the original (.root) page as 
 | 
					
						
							|  |  |  | 				// 		the common root...
 | 
					
						
							|  |  |  | 				// 		this will make all the non-shadowed attrs set on the
 | 
					
						
							|  |  |  | 				// 		root visible to all sub-pages.
 | 
					
						
							| 
									
										
										
										
											2022-08-12 01:38:32 +03:00
										 |  |  | 				: Object.create(src), | 
					
						
							| 
									
										
										
										
											2022-08-15 14:29:45 +03:00
										 |  |  | 			// XXX
 | 
					
						
							|  |  |  | 			//{...this},
 | 
					
						
							| 
									
										
										
										
											2022-08-04 11:00:21 +03:00
										 |  |  | 			{ | 
					
						
							|  |  |  | 				root: this.root ?? this, | 
					
						
							|  |  |  | 				location: this.location,  | 
					
						
							|  |  |  | 				referrer: this.referrer, | 
					
						
							|  |  |  | 			}, | 
					
						
							|  |  |  | 			data) }, | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// Create a read-only page...
 | 
					
						
							|  |  |  | 	//
 | 
					
						
							|  |  |  | 	// NOTE: all pages that are created via a read-only page are also 
 | 
					
						
							|  |  |  | 	// 		read-only.
 | 
					
						
							|  |  |  | 	// XXX EXPERIMENTAL...
 | 
					
						
							|  |  |  | 	ro: function(data={}){ | 
					
						
							|  |  |  | 		return Object.assign({ | 
					
						
							|  |  |  | 			__proto__: this, | 
					
						
							|  |  |  | 			__update__: function(){ return this }, | 
					
						
							|  |  |  | 			__delete__: function(){ return this }, | 
					
						
							|  |  |  | 		}, | 
					
						
							|  |  |  | 		data) }, | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// Create a virtual page at current path...
 | 
					
						
							|  |  |  | 	//
 | 
					
						
							|  |  |  | 	// Virtual pages do not affect store data in any way but behave like 
 | 
					
						
							|  |  |  | 	// normal pages.
 | 
					
						
							|  |  |  | 	//
 | 
					
						
							|  |  |  | 	// NOTE: .get(..) / .clone(..) will return normal non-virtual pages
 | 
					
						
							|  |  |  | 	// 		unless the target path is the same as the virtual page .path...
 | 
					
						
							|  |  |  | 	// NOTE: changing .path/.location is not supported.
 | 
					
						
							|  |  |  | 	// XXX EXPERIMENTAL...
 | 
					
						
							|  |  |  | 	virtual: function(data={}){ | 
					
						
							|  |  |  | 		var that = this | 
					
						
							|  |  |  | 		return { | 
					
						
							|  |  |  | 			__proto__: this, | 
					
						
							|  |  |  | 			// make the location read-only...
 | 
					
						
							|  |  |  | 			get location(){ | 
					
						
							|  |  |  | 				// NOTE: since we are not providing this as a basis for 
 | 
					
						
							|  |  |  | 				// 		inheritance we do not need to properly access 
 | 
					
						
							|  |  |  | 				// 		the parent prop...
 | 
					
						
							|  |  |  | 				// 		...otherwise use:
 | 
					
						
							|  |  |  | 				// 			object.parentProperty(..)
 | 
					
						
							|  |  |  | 				return this.__proto__.location }, | 
					
						
							|  |  |  | 			__update__: function(data){  | 
					
						
							|  |  |  | 				Object.assign(this.data, data) | 
					
						
							|  |  |  | 				return this }, | 
					
						
							|  |  |  | 			__delete__: function(){ return this }, | 
					
						
							|  |  |  | 			// NOTE: we need to proxy .clone(..) back to parent so as to 
 | 
					
						
							|  |  |  | 			// 		avoid overloading .data in the children too...
 | 
					
						
							|  |  |  | 			// NOTE: we are also keeping all first level queries resolving 
 | 
					
						
							|  |  |  | 			// 		to current path also virtual...
 | 
					
						
							|  |  |  | 			clone: function(...args){ | 
					
						
							|  |  |  | 				var res = that.clone(...args)  | 
					
						
							|  |  |  | 				return res.path == this.path ? | 
					
						
							|  |  |  | 					that.virtual(this.data) | 
					
						
							|  |  |  | 					: res }, | 
					
						
							|  |  |  | 			data: Object.assign( | 
					
						
							|  |  |  | 				{ | 
					
						
							|  |  |  | 					ctime: Date.now(), | 
					
						
							|  |  |  | 					mtime: Date.now(), | 
					
						
							|  |  |  | 				}, | 
					
						
							|  |  |  | 				data), | 
					
						
							|  |  |  | 		} }, | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// XXX should this be update or assign???
 | 
					
						
							|  |  |  | 	// XXX how should this work on multiple pages...
 | 
					
						
							|  |  |  | 	// 		...right now this will write what-ever is given, even if it
 | 
					
						
							|  |  |  | 	// 		will never be explicitly be accessible...
 | 
					
						
							|  |  |  | 	// XXX sync/async???
 | 
					
						
							| 
									
										
										
										
											2022-10-31 02:29:21 +03:00
										 |  |  | 	update: types.event.Event('update', | 
					
						
							|  |  |  | 		function(_, ...data){ | 
					
						
							|  |  |  | 			return Object.assign(this, ...data) }), | 
					
						
							| 
									
										
										
										
											2022-08-04 11:00:21 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-08-10 11:42:31 +03:00
										 |  |  | 	// XXX should this take an options/dict argument????
 | 
					
						
							| 
									
										
										
										
											2022-08-04 11:00:21 +03:00
										 |  |  | 	__init__: function(path, referrer, store){ | 
					
						
							| 
									
										
										
										
											2022-08-10 11:42:31 +03:00
										 |  |  | 		if(referrer && typeof(referrer) != 'string'){ | 
					
						
							|  |  |  | 			store = referrer | 
					
						
							|  |  |  | 			referrer = undefined } | 
					
						
							| 
									
										
										
										
											2022-08-04 11:00:21 +03:00
										 |  |  | 		// NOTE: this will allow inheriting .store from the prototype
 | 
					
						
							|  |  |  | 		if(store){ | 
					
						
							|  |  |  | 			this.store = store } | 
					
						
							|  |  |  | 		this.location = path | 
					
						
							|  |  |  | 		this.referrer = referrer }, | 
					
						
							|  |  |  | }) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // pepper in event functionality...
 | 
					
						
							|  |  |  | types.event.EventMixin(BasePage.prototype) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-08-04 14:29:25 +03:00
										 |  |  | //---------------------------------------------------------------------
 | 
					
						
							| 
									
										
										
										
											2022-08-04 11:00:21 +03:00
										 |  |  | 
 | 
					
						
							|  |  |  | var Page = | 
					
						
							|  |  |  | module.Page =  | 
					
						
							|  |  |  | object.Constructor('Page', BasePage, { | 
					
						
							|  |  |  | 	__parser__: parser.parser, | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-08-27 16:30:23 +03:00
										 |  |  | 	NESTING_DEPTH_LIMIT: 20, | 
					
						
							| 
									
										
										
										
											2022-08-27 16:17:25 +03:00
										 |  |  | 	NESTING_RECURSION_TEST_THRESHOLD: 50, | 
					
						
							| 
									
										
										
										
											2022-08-17 11:46:50 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-08-04 11:00:21 +03:00
										 |  |  | 	// Filter that will isolate the page/include/.. from parent filters...
 | 
					
						
							|  |  |  | 	ISOLATED_FILTERS: 'isolated', | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// list of macros that will get raw text of their content...
 | 
					
						
							|  |  |  | 	QUOTING_MACROS: ['quote'], | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// templates used to render a page via .text
 | 
					
						
							| 
									
										
										
										
											2022-08-17 23:38:24 +03:00
										 |  |  | 	PAGE_TEMPLATE: '_view', | 
					
						
							| 
									
										
										
										
											2022-08-04 11:00:21 +03:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	// NOTE: comment this out to make the system fail when nothing is 
 | 
					
						
							|  |  |  | 	// 		resolved, not even the System/NotFound page...
 | 
					
						
							|  |  |  | 	// NOTE: we can't use any of the page actions here (like @source(./path)) 
 | 
					
						
							|  |  |  | 	// 		as if we reach this it's likely all the bootstrap is either also
 | 
					
						
							|  |  |  | 	// 		not present or broken.
 | 
					
						
							|  |  |  | 	// NOTE: to force the system to fail set this to undefined.
 | 
					
						
							| 
									
										
										
										
											2022-08-05 02:47:31 +03:00
										 |  |  | 	NOT_FOUND_ERROR: 'NotFoundError', | 
					
						
							|  |  |  | 	RECURSION_ERROR: 'RecursionError', | 
					
						
							| 
									
										
										
										
											2022-08-18 01:23:49 +03:00
										 |  |  | 	NOT_FOUND_TEMPLATE_ERROR: 'NotFoundTemplateError', | 
					
						
							| 
									
										
										
										
											2022-08-21 23:07:47 +03:00
										 |  |  | 	QUOTE_ACTION_PAGE: 'QuoteActionPage', | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-08-21 18:10:39 +03:00
										 |  |  | 	// Format:
 | 
					
						
							|  |  |  | 	// 	{
 | 
					
						
							|  |  |  | 	// 		<path>: Set([<path>, ...]),
 | 
					
						
							|  |  |  | 	// 	}
 | 
					
						
							|  |  |  | 	//
 | 
					
						
							| 
									
										
										
										
											2022-08-22 13:24:26 +03:00
										 |  |  | 	// NOTE: this is stored in .root...
 | 
					
						
							| 
									
										
										
										
											2022-08-22 12:43:49 +03:00
										 |  |  | 	//__dependencies: undefined,
 | 
					
						
							|  |  |  | 	get dependencies(){ | 
					
						
							|  |  |  | 		return (this.root ?? this).__dependencies ?? {} }, | 
					
						
							|  |  |  | 	set dependencies(value){ | 
					
						
							|  |  |  | 		((this.root ?? this).__dependencies) = value }, | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-08-21 18:10:39 +03:00
										 |  |  | 	// NOTE: for this to populate .text must be done at least once...
 | 
					
						
							|  |  |  | 	get depends(){ | 
					
						
							|  |  |  | 		return (this.dependencies ?? {})[this.path] }, | 
					
						
							|  |  |  | 	set depends(value){ | 
					
						
							| 
									
										
										
										
											2022-08-22 10:07:22 +03:00
										 |  |  | 		if(value == null){ | 
					
						
							|  |  |  | 			delete (this.dependencies ?? {})[this.path] | 
					
						
							|  |  |  | 		} else { | 
					
						
							|  |  |  | 			;(this.dependencies = this.dependencies ?? {})[this.path] = value } }, | 
					
						
							| 
									
										
										
										
											2022-08-21 18:10:39 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-08-16 09:35:07 +03:00
										 |  |  | 	// The page that started the current render...
 | 
					
						
							|  |  |  | 	//
 | 
					
						
							|  |  |  | 	// This is set by .text and maintained by .clone(..).
 | 
					
						
							|  |  |  | 	//
 | 
					
						
							|  |  |  | 	// NOTE: for manual rendering (.parse(..), ... etc.) this has to be 
 | 
					
						
							|  |  |  | 	// 		setup manually.
 | 
					
						
							| 
									
										
										
										
											2022-09-05 00:57:42 +03:00
										 |  |  | 	//renderer: undefined,
 | 
					
						
							| 
									
										
										
										
											2022-09-02 14:58:45 +03:00
										 |  |  | 	get renderer(){ | 
					
						
							| 
									
										
										
										
											2022-09-05 00:57:42 +03:00
										 |  |  | 		return this.__render_root ?? this }, | 
					
						
							|  |  |  | 	set renderer(value){ | 
					
						
							|  |  |  | 		this.__render_root = value }, | 
					
						
							| 
									
										
										
										
											2022-09-02 14:58:45 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-08-04 11:00:21 +03:00
										 |  |  | 	//
 | 
					
						
							|  |  |  | 	// 	<filter>(<source>)
 | 
					
						
							|  |  |  | 	// 		-> <result>
 | 
					
						
							|  |  |  | 	// 		-> undefined
 | 
					
						
							|  |  |  | 	//
 | 
					
						
							|  |  |  | 	// XXX might be a good idea to fix filter order...
 | 
					
						
							|  |  |  | 	filters: { | 
					
						
							|  |  |  | 		// placeholders...
 | 
					
						
							|  |  |  | 		nofilters: function(){}, | 
					
						
							|  |  |  | 		isolated: function(){}, | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		// XXX TESTING...
 | 
					
						
							|  |  |  | 		dummy: function(){}, | 
					
						
							|  |  |  | 		test: function(source){ | 
					
						
							|  |  |  | 			return source  | 
					
						
							|  |  |  | 				.replace(/test/g, 'TEST') }, | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-08-14 02:08:27 +03:00
										 |  |  | 		'quote-tags': function(source){ | 
					
						
							|  |  |  | 			return source | 
					
						
							|  |  |  | 				.replace(/&/g, '&') | 
					
						
							|  |  |  | 				.replace(/</g, '<') | 
					
						
							|  |  |  | 				.replace(/>/g, '>') }, | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-08-09 11:15:37 +03:00
										 |  |  | 		// XXX one way to do this in a stable manner is to wrap the source 
 | 
					
						
							|  |  |  | 		// 		in something like <span wikiwords=yes> .. </span> and only 
 | 
					
						
							|  |  |  | 		// 		process those removing the wrapper in dom...
 | 
					
						
							| 
									
										
										
										
											2022-08-10 11:42:31 +03:00
										 |  |  | 		// 		...not sure how to handle -wikiword filter calls -- now 
 | 
					
						
							|  |  |  | 		// 		this is entirely handled by the parser without calling this...
 | 
					
						
							| 
									
										
										
										
											2022-08-08 23:04:42 +03:00
										 |  |  | 		wikiword: function(){},  | 
					
						
							|  |  |  | 		'quote-wikiword': function(){}, | 
					
						
							| 
									
										
										
										
											2022-08-04 14:29:25 +03:00
										 |  |  | 
 | 
					
						
							|  |  |  | 		markdown: markdown.markdown, | 
					
						
							|  |  |  | 		'quote-markdown': markdown.quoteMarkdown, | 
					
						
							| 
									
										
										
										
											2022-08-04 19:47:08 +03:00
										 |  |  | 
 | 
					
						
							|  |  |  | 		text: function(source){ | 
					
						
							|  |  |  | 			return `<pre>${source}</pre>` }, | 
					
						
							| 
									
										
										
										
											2022-08-04 11:00:21 +03:00
										 |  |  | 	}, | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-11-20 02:14:50 +03:00
										 |  |  | 	// XXX EXPERIMENTAL...
 | 
					
						
							|  |  |  | 	//
 | 
					
						
							|  |  |  | 	// 	Define a global macro...
 | 
					
						
							|  |  |  | 	// 	.defmacro(<name>, <func>)
 | 
					
						
							|  |  |  | 	// 	.defmacro(<name>, <args>, <func>)
 | 
					
						
							|  |  |  | 	// 		-> this
 | 
					
						
							|  |  |  | 	//
 | 
					
						
							| 
									
										
										
										
											2023-09-24 14:30:32 +03:00
										 |  |  | 	/* XXX do we need this??? | 
					
						
							| 
									
										
										
										
											2022-11-20 02:14:50 +03:00
										 |  |  | 	defmacro: function(name, args, func){ | 
					
						
							| 
									
										
										
										
											2023-09-24 14:30:32 +03:00
										 |  |  | 		this.__parser__.macros[name] =  | 
					
						
							| 
									
										
										
										
											2022-11-20 02:14:50 +03:00
										 |  |  | 			arguments.length == 2 ? | 
					
						
							|  |  |  | 				arguments[1] | 
					
						
							|  |  |  | 				: Macro(args, func) | 
					
						
							|  |  |  | 		return this }, | 
					
						
							| 
									
										
										
										
											2023-09-24 14:30:32 +03:00
										 |  |  | 	//*/
 | 
					
						
							| 
									
										
										
										
											2022-11-20 02:14:50 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-08-04 11:00:21 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-09-02 14:58:45 +03:00
										 |  |  | 	// direct actions...
 | 
					
						
							|  |  |  | 	//
 | 
					
						
							|  |  |  | 	// These are evaluated directly without the need to go through the 
 | 
					
						
							|  |  |  | 	// whole page acquisition process...
 | 
					
						
							|  |  |  | 	//
 | 
					
						
							|  |  |  | 	// NOTE: these can not be overloaded. 
 | 
					
						
							|  |  |  | 	// 		(XXX should this be so?)
 | 
					
						
							| 
									
										
										
										
											2022-09-02 17:27:40 +03:00
										 |  |  | 	// XXX should this be an object???
 | 
					
						
							| 
									
										
										
										
											2022-09-17 17:13:23 +03:00
										 |  |  | 	actions: { | 
					
						
							| 
									
										
										
										
											2022-09-02 17:27:40 +03:00
										 |  |  | 		...module.BasePage.prototype.actions, | 
					
						
							| 
									
										
										
										
											2022-09-02 14:58:45 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-09-17 17:13:23 +03:00
										 |  |  | 		'!': true, | 
					
						
							| 
									
										
										
										
											2022-12-02 02:43:36 +03:00
										 |  |  | 		// XXX EXPERIMENTAL...
 | 
					
						
							|  |  |  | 		quote: true, | 
					
						
							| 
									
										
										
										
											2022-09-17 17:13:23 +03:00
										 |  |  | 	}, | 
					
						
							| 
									
										
										
										
											2022-09-02 14:58:45 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-12-02 02:43:36 +03:00
										 |  |  | 	// XXX should this be .raw or .parse()???
 | 
					
						
							| 
									
										
										
										
											2022-09-02 17:27:40 +03:00
										 |  |  | 	'!': Object.assign( | 
					
						
							|  |  |  | 		function(){ | 
					
						
							| 
									
										
										
										
											2022-09-18 20:45:55 +03:00
										 |  |  | 			return this.get('..:$ARGS', {energetic: true}).raw }, | 
					
						
							| 
									
										
										
										
											2022-09-02 17:27:40 +03:00
										 |  |  | 		{energetic: true}), | 
					
						
							| 
									
										
										
										
											2022-12-02 02:43:36 +03:00
										 |  |  | 	// XXX EXPERIMENTAL...
 | 
					
						
							|  |  |  | 	// XXX this is html/web specific, should it be here???
 | 
					
						
							|  |  |  | 	// 		...
 | 
					
						
							|  |  |  | 	// XXX should this be .raw or .parse()???
 | 
					
						
							| 
									
										
										
										
											2023-02-11 23:12:51 +03:00
										 |  |  | 	// XXX ASYNC???
 | 
					
						
							| 
									
										
										
										
											2022-12-02 03:19:16 +03:00
										 |  |  | 	quote: async function(energetic=false){ | 
					
						
							| 
									
										
										
										
											2023-02-11 23:12:51 +03:00
										 |  |  | 		return Promise.awaitOrRun( | 
					
						
							|  |  |  | 			this.get('..:$ARGS', {energetic: await this.energetic}).raw, | 
					
						
							|  |  |  | 			function(res){ | 
					
						
							| 
									
										
										
										
											2022-12-02 02:43:36 +03:00
										 |  |  | 				return res instanceof Array ? | 
					
						
							|  |  |  | 					res.map(pwpath.quoteHTML) | 
					
						
							|  |  |  | 					: pwpath.quoteHTML(res) }) }, | 
					
						
							| 
									
										
										
										
											2022-09-02 17:27:40 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-09-05 00:57:42 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-08-04 11:00:21 +03:00
										 |  |  | 	// events...
 | 
					
						
							|  |  |  | 	//
 | 
					
						
							|  |  |  | 	// NOTE: textUpdate event will not get triggered if text is updated 
 | 
					
						
							|  |  |  | 	// 		directly via .data or .__update__(..)
 | 
					
						
							|  |  |  | 	/*/ XXX EVENTS do we need this??? | 
					
						
							|  |  |  | 	onTextUpdate: types.event.Event('textUpdate', | 
					
						
							|  |  |  | 		function(handle, text){ | 
					
						
							|  |  |  | 			this.__update__({text}) }), | 
					
						
							|  |  |  | 	// XXX EVENTS not sure where to trigger this???
 | 
					
						
							|  |  |  | 	// 		...on .parse(..) is a bit too granular, something like .text??
 | 
					
						
							|  |  |  | 	// XXX not triggered yet...
 | 
					
						
							|  |  |  | 	//onParse: types.event.Event('parse'),
 | 
					
						
							|  |  |  | 	//*/
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// page parser...
 | 
					
						
							|  |  |  | 	//
 | 
					
						
							| 
									
										
										
										
											2022-09-09 17:15:15 +03:00
										 |  |  | 	// NOTE: .__debug_last_render_state is mainly exposed for introspection 
 | 
					
						
							|  |  |  | 	// 		and debugging, set comment it out to disable...
 | 
					
						
							|  |  |  | 	//__debug_last_render_state: undefined,
 | 
					
						
							| 
									
										
										
										
											2022-12-02 02:43:36 +03:00
										 |  |  | 	// XXX should this handle pattern paths???
 | 
					
						
							| 
									
										
										
										
											2023-02-19 14:27:50 +03:00
										 |  |  | 	// XXX this might be a good spot to cache .raw in state...
 | 
					
						
							| 
									
										
										
										
											2023-02-11 05:05:32 +03:00
										 |  |  | 	parse: function(text, state){ | 
					
						
							|  |  |  | 		var that = this | 
					
						
							| 
									
										
										
										
											2023-02-19 14:27:50 +03:00
										 |  |  | 		// .parser(<state>)
 | 
					
						
							|  |  |  | 		if(arguments.length == 1  | 
					
						
							|  |  |  | 				&& text instanceof Object | 
					
						
							|  |  |  | 				&& !(text instanceof Array)){ | 
					
						
							|  |  |  | 			state = text | 
					
						
							|  |  |  | 			text = null } | 
					
						
							| 
									
										
										
										
											2023-02-11 05:05:32 +03:00
										 |  |  | 		return Promise.awaitOrRun( | 
					
						
							| 
									
										
										
										
											2023-02-19 14:27:50 +03:00
										 |  |  | 			//text,
 | 
					
						
							|  |  |  | 			text  | 
					
						
							|  |  |  | 				?? this.raw, | 
					
						
							| 
									
										
										
										
											2023-02-11 05:05:32 +03:00
										 |  |  | 			function(text){ | 
					
						
							|  |  |  | 				state = state ?? {} | 
					
						
							|  |  |  | 				state.renderer = state.renderer ?? that | 
					
						
							|  |  |  | 				// this is here for debugging and introspection...
 | 
					
						
							|  |  |  | 				'__debug_last_render_state' in that | 
					
						
							|  |  |  | 					&& (that.__debug_last_render_state = state) | 
					
						
							|  |  |  | 				// parse...
 | 
					
						
							|  |  |  | 				return that.__parser__.parse( | 
					
						
							|  |  |  | 					that.get('.', { | 
					
						
							|  |  |  | 						renderer: state.renderer, | 
					
						
							|  |  |  | 						args: that.args,  | 
					
						
							|  |  |  | 					}),  | 
					
						
							| 
									
										
										
										
											2023-02-19 14:27:50 +03:00
										 |  |  | 					text, | 
					
						
							| 
									
										
										
										
											2023-02-11 05:05:32 +03:00
										 |  |  | 					state) }) }, | 
					
						
							| 
									
										
										
										
											2022-08-04 11:00:21 +03:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	// raw page text...
 | 
					
						
							|  |  |  | 	//
 | 
					
						
							|  |  |  | 	// NOTE: writing to .raw is the same as writing to .text...
 | 
					
						
							|  |  |  | 	// NOTE: when matching multiple pages this will return a list...
 | 
					
						
							| 
									
										
										
										
											2022-08-28 16:34:46 +03:00
										 |  |  | 	//
 | 
					
						
							|  |  |  | 	// XXX revise how we handle .strict mode...
 | 
					
						
							| 
									
										
										
										
											2023-02-11 23:12:51 +03:00
										 |  |  | 	get raw(){ | 
					
						
							|  |  |  | 		var that = this | 
					
						
							|  |  |  | 		return Promise.awaitOrRun( | 
					
						
							|  |  |  | 			this.data, | 
					
						
							|  |  |  | 			function(data){ | 
					
						
							|  |  |  | 				// no data...
 | 
					
						
							|  |  |  | 				// NOTE: if we hit this it means that nothing was resolved, 
 | 
					
						
							|  |  |  | 				// 		not even the System/NotFound page, i.e. something 
 | 
					
						
							|  |  |  | 				// 		went really wrong...
 | 
					
						
							|  |  |  | 				// NOTE: in .strict mode this will explicitly fail and not try 
 | 
					
						
							|  |  |  | 				// 		to recover...
 | 
					
						
							|  |  |  | 				if(data == null){ | 
					
						
							|  |  |  | 					if(!this.strict  | 
					
						
							|  |  |  | 							&& this.NOT_FOUND_ERROR){ | 
					
						
							|  |  |  | 						var msg = this.get(this.NOT_FOUND_ERROR) | 
					
						
							|  |  |  | 						return Promise.awaitOrRun( | 
					
						
							|  |  |  | 							msg.match(), | 
					
						
							|  |  |  | 							function(msg){ | 
					
						
							|  |  |  | 								return msg.raw }) } | 
					
						
							|  |  |  | 					// last resort...
 | 
					
						
							|  |  |  | 					throw new Error('NOT FOUND ERROR: '+ this.path) } | 
					
						
							|  |  |  | 				// get the data...
 | 
					
						
							|  |  |  | 				return ( | 
					
						
							|  |  |  | 					// action...
 | 
					
						
							|  |  |  | 					typeof(data) == 'function' ? | 
					
						
							|  |  |  | 						data() | 
					
						
							|  |  |  | 					// multiple matches...
 | 
					
						
							|  |  |  | 					: data instanceof Array ? | 
					
						
							|  |  |  | 						// XXX
 | 
					
						
							|  |  |  | 						Promise.all(data | 
					
						
							|  |  |  | 							.map(function(d){ | 
					
						
							|  |  |  | 								return typeof(d) == 'function'? | 
					
						
							|  |  |  | 									d() | 
					
						
							|  |  |  | 									: d.text }) | 
					
						
							|  |  |  | 							.flat()) | 
					
						
							|  |  |  | 					: data.text ) },  | 
					
						
							|  |  |  | 			null) }, | 
					
						
							| 
									
										
										
										
											2022-08-04 11:00:21 +03:00
										 |  |  | 	set raw(value){ | 
					
						
							| 
									
										
										
										
											2022-09-19 00:18:23 +03:00
										 |  |  | 		this.data = {text: value} }, | 
					
						
							| 
									
										
										
										
											2022-08-04 11:00:21 +03:00
										 |  |  | 		//this.onTextUpdate(value) },
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-08-19 19:40:28 +03:00
										 |  |  | 	// iterate matches or content list as pages...
 | 
					
						
							|  |  |  | 	//
 | 
					
						
							| 
									
										
										
										
											2022-08-21 23:07:47 +03:00
										 |  |  | 	// 	.asPages()
 | 
					
						
							|  |  |  | 	// 	.asPages(<path>[, <options>])
 | 
					
						
							|  |  |  | 	// 	.asPages(<strict>[, <options>])
 | 
					
						
							|  |  |  | 	// 	.asPages(<path>, <strict>[, <options>])
 | 
					
						
							|  |  |  | 	// 	.asPages(<options>)
 | 
					
						
							|  |  |  | 	// 		-> <iter>
 | 
					
						
							|  |  |  | 	//
 | 
					
						
							|  |  |  | 	// NOTE: this will get .raw for non-pattern pages this it can trigger 
 | 
					
						
							|  |  |  | 	// 		actions...
 | 
					
						
							|  |  |  | 	//
 | 
					
						
							| 
									
										
										
										
											2022-08-19 19:40:28 +03:00
										 |  |  | 	// XXX revise name...
 | 
					
						
							| 
									
										
										
										
											2023-02-20 05:38:55 +03:00
										 |  |  | 	// XXX do we need both this and .each(..)
 | 
					
						
							|  |  |  | 	// 		...what is the difference???
 | 
					
						
							|  |  |  | 	// 			- handle path slightly differently...
 | 
					
						
							|  |  |  | 	// 			- .asPages(..) handles list/generator pages...
 | 
					
						
							| 
									
										
										
										
											2023-02-19 15:05:12 +03:00
										 |  |  | 	// XXX BUG: this does not respect strict of single pages if they do 
 | 
					
						
							|  |  |  | 	// 		not exist...
 | 
					
						
							|  |  |  | 	// 		...see: @macro(..) bug + .each(..)
 | 
					
						
							| 
									
										
										
										
											2023-02-19 15:07:38 +03:00
										 |  |  | 	// 		FIXED: revise...
 | 
					
						
							| 
									
										
										
										
											2022-09-09 19:18:09 +03:00
										 |  |  | 	asPages: async function*(path='.:$ARGS', strict=false){ | 
					
						
							| 
									
										
										
										
											2022-08-21 23:07:47 +03:00
										 |  |  | 		// options...
 | 
					
						
							|  |  |  | 		var args = [...arguments] | 
					
						
							|  |  |  | 		var opts = typeof(args.at(-1)) == 'object' ? | 
					
						
							|  |  |  | 			args.pop() | 
					
						
							|  |  |  | 			: {} | 
					
						
							| 
									
										
										
										
											2022-09-09 19:18:09 +03:00
										 |  |  | 		var {path, strict} = { | 
					
						
							| 
									
										
										
										
											2022-08-21 23:07:47 +03:00
										 |  |  | 			...opts, | 
					
						
							|  |  |  | 			path: typeof(args[0]) == 'string' ? | 
					
						
							|  |  |  | 				args.shift() | 
					
						
							| 
									
										
										
										
											2022-09-07 16:37:26 +03:00
										 |  |  | 				: '.:$ARGS', | 
					
						
							| 
									
										
										
										
											2022-09-02 17:27:40 +03:00
										 |  |  | 			strict: args.shift()  | 
					
						
							|  |  |  | 				?? false, | 
					
						
							| 
									
										
										
										
											2022-08-21 23:07:47 +03:00
										 |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-08-19 19:40:28 +03:00
										 |  |  | 		var page = this.get(path, strict) | 
					
						
							| 
									
										
										
										
											2022-09-09 19:18:09 +03:00
										 |  |  | 		// each...
 | 
					
						
							|  |  |  | 		if(page.isPattern){ | 
					
						
							|  |  |  | 			yield* page | 
					
						
							| 
									
										
										
										
											2022-08-19 19:40:28 +03:00
										 |  |  | 		// handle lists in pages (actions, ... etc.)...
 | 
					
						
							| 
									
										
										
										
											2022-09-09 19:18:09 +03:00
										 |  |  | 		} else { | 
					
						
							| 
									
										
										
										
											2023-02-20 02:21:22 +03:00
										 |  |  | 			// strict + page does not exist...
 | 
					
						
							| 
									
										
										
										
											2023-02-19 15:07:38 +03:00
										 |  |  | 			if(strict  | 
					
						
							|  |  |  | 					&& !(await page.exists())){ | 
					
						
							|  |  |  | 				return } | 
					
						
							| 
									
										
										
										
											2022-09-09 19:18:09 +03:00
										 |  |  | 			var data = await page.data | 
					
						
							| 
									
										
										
										
											2022-09-22 02:52:14 +03:00
										 |  |  | 			data =  | 
					
						
							| 
									
										
										
										
											2022-11-18 03:26:33 +03:00
										 |  |  | 				data instanceof types.Generator ? | 
					
						
							| 
									
										
										
										
											2022-09-22 02:52:14 +03:00
										 |  |  | 					await data() | 
					
						
							| 
									
										
										
										
											2022-11-18 03:26:33 +03:00
										 |  |  | 				: typeof(data) == 'function' ? | 
					
						
							|  |  |  | 					data | 
					
						
							| 
									
										
										
										
											2022-11-29 20:22:46 +03:00
										 |  |  | 				: data && 'text' in data ? | 
					
						
							| 
									
										
										
										
											2022-09-09 19:18:09 +03:00
										 |  |  | 					data.text | 
					
						
							|  |  |  | 				: null | 
					
						
							|  |  |  | 			if(data instanceof Array | 
					
						
							|  |  |  | 					|| data instanceof types.Generator){ | 
					
						
							|  |  |  | 				yield* data | 
					
						
							|  |  |  | 					.map(function(p){ | 
					
						
							|  |  |  | 						return page.virtual({text: p}) }) | 
					
						
							|  |  |  | 				return } | 
					
						
							| 
									
										
										
										
											2022-09-22 02:52:14 +03:00
										 |  |  | 			// do not iterate pages/actions that are undefined...
 | 
					
						
							|  |  |  | 			if(data == null){ | 
					
						
							|  |  |  | 				return } | 
					
						
							| 
									
										
										
										
											2022-09-09 19:18:09 +03:00
										 |  |  | 
 | 
					
						
							|  |  |  | 			yield page } }, | 
					
						
							| 
									
										
										
										
											2022-08-19 19:40:28 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-08-04 11:00:21 +03:00
										 |  |  | 	// expanded page text...
 | 
					
						
							|  |  |  | 	//
 | 
					
						
							| 
									
										
										
										
											2022-08-05 18:21:18 +03:00
										 |  |  | 	// NOTE: this uses .PAGE_TEMPLATE to render the page.
 | 
					
						
							| 
									
										
										
										
											2022-08-04 11:00:21 +03:00
										 |  |  | 	// NOTE: writing to .raw is the same as writing to .text...
 | 
					
						
							| 
									
										
										
										
											2022-08-25 11:28:01 +03:00
										 |  |  | 	//
 | 
					
						
							| 
									
										
										
										
											2022-09-18 20:12:18 +03:00
										 |  |  | 	// XXX should render templates (_view and the like) be a special case
 | 
					
						
							|  |  |  | 	// 		or render as any other page???
 | 
					
						
							|  |  |  | 	// 		...currently they are rendered in the context of the page and
 | 
					
						
							|  |  |  | 	// 		not in their own context...
 | 
					
						
							| 
									
										
										
										
											2023-02-12 16:08:00 +03:00
										 |  |  | 	// XXX revise how we handle strict mode...
 | 
					
						
							|  |  |  | 	// XXX would be nice to be able to chain .awaitOrRun(..) calls instead 
 | 
					
						
							|  |  |  | 	// 		of nesting them like here...
 | 
					
						
							| 
									
										
										
										
											2023-02-11 23:12:51 +03:00
										 |  |  | 	get text(){ | 
					
						
							| 
									
										
										
										
											2023-02-12 17:35:17 +03:00
										 |  |  | 		var that = this | 
					
						
							| 
									
										
										
										
											2023-02-11 23:12:51 +03:00
										 |  |  | 		return Promise.awaitOrRun( | 
					
						
							| 
									
										
										
										
											2023-02-12 17:35:17 +03:00
										 |  |  | 			!that.strict | 
					
						
							|  |  |  | 				|| that.resolve(true), | 
					
						
							| 
									
										
										
										
											2023-02-12 16:08:00 +03:00
										 |  |  | 			function(exists){ | 
					
						
							|  |  |  | 				// strict mode -- break on non-existing pages...
 | 
					
						
							|  |  |  | 				if(!exists){ | 
					
						
							| 
									
										
										
										
											2023-02-12 17:35:17 +03:00
										 |  |  | 					throw new Error('NOT FOUND ERROR: '+ that.location) } | 
					
						
							| 
									
										
										
										
											2023-02-12 16:08:00 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-02-12 17:35:17 +03:00
										 |  |  | 				var path = pwpath.split(that.path) | 
					
						
							| 
									
										
										
										
											2023-02-12 16:08:00 +03:00
										 |  |  | 				;(path.at(-1) ?? '')[0] == '_' | 
					
						
							| 
									
										
										
										
											2023-02-12 17:35:17 +03:00
										 |  |  | 					|| path.push(that.PAGE_TEMPLATE) | 
					
						
							| 
									
										
										
										
											2023-02-12 16:08:00 +03:00
										 |  |  | 				var tpl = pwpath.join(path) | 
					
						
							|  |  |  | 				var tpl_name = path.pop() | 
					
						
							|  |  |  | 				//var tpl_name = path.at(-1)
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 				// get the template relative to the top most pattern...
 | 
					
						
							|  |  |  | 				return Promise.awaitOrRun( | 
					
						
							| 
									
										
										
										
											2023-02-12 17:35:17 +03:00
										 |  |  | 					that.get(tpl).find(true), | 
					
						
							| 
									
										
										
										
											2023-02-12 16:08:00 +03:00
										 |  |  | 					function(tpl){ | 
					
						
							|  |  |  | 						if(!tpl){ | 
					
						
							|  |  |  | 							console.warn('UNKNOWN RENDER TEMPLATE: '+ tpl_name)  | 
					
						
							| 
									
										
										
										
											2023-02-12 17:35:17 +03:00
										 |  |  | 							return that.get(that.NOT_FOUND_TEMPLATE_ERROR).parse() } | 
					
						
							| 
									
										
										
										
											2023-02-12 16:08:00 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-02-12 17:35:17 +03:00
										 |  |  | 						var depends = that.depends = new Set([tpl]) | 
					
						
							| 
									
										
										
										
											2023-02-12 16:08:00 +03:00
										 |  |  | 						// do the parse...
 | 
					
						
							|  |  |  | 						// NOTE: we render the template in context of page...
 | 
					
						
							| 
									
										
										
										
											2023-02-12 17:35:17 +03:00
										 |  |  | 						return that | 
					
						
							|  |  |  | 							// NOTE: that.path can both contain a template and not, this
 | 
					
						
							| 
									
										
										
										
											2023-02-12 16:08:00 +03:00
										 |  |  | 							// 		normalizes it to the path up to the template path...
 | 
					
						
							| 
									
										
										
										
											2023-02-12 17:35:17 +03:00
										 |  |  | 							.get(path, {args: that.args}) | 
					
						
							| 
									
										
										
										
											2023-02-12 16:08:00 +03:00
										 |  |  | 							.parse( | 
					
						
							| 
									
										
										
										
											2023-02-12 17:35:17 +03:00
										 |  |  | 								that.get( | 
					
						
							| 
									
										
										
										
											2023-02-12 16:08:00 +03:00
										 |  |  | 									'/'+tpl,  | 
					
						
							| 
									
										
										
										
											2023-02-12 17:35:17 +03:00
										 |  |  | 									{args: that.args}).raw,  | 
					
						
							| 
									
										
										
										
											2023-02-12 16:08:00 +03:00
										 |  |  | 								{ | 
					
						
							|  |  |  | 									depends,  | 
					
						
							| 
									
										
										
										
											2023-02-12 17:35:17 +03:00
										 |  |  | 									renderer: that, | 
					
						
							|  |  |  | 								}) }) }) }, | 
					
						
							| 
									
										
										
										
											2022-08-04 11:00:21 +03:00
										 |  |  | 	set text(value){ | 
					
						
							| 
									
										
										
										
											2022-09-19 00:18:23 +03:00
										 |  |  | 		this.data = {text: value} }, | 
					
						
							| 
									
										
										
										
											2022-08-04 11:00:21 +03:00
										 |  |  | 		//this.onTextUpdate(value) },
 | 
					
						
							| 
									
										
										
										
											2022-08-15 14:29:45 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-09-05 00:57:42 +03:00
										 |  |  | 	// pass on .renderer to clones...
 | 
					
						
							| 
									
										
										
										
											2022-08-15 14:29:45 +03:00
										 |  |  | 	clone: function(data={}, ...args){ | 
					
						
							| 
									
										
										
										
											2022-09-05 00:57:42 +03:00
										 |  |  | 		this.renderer | 
					
						
							|  |  |  | 			&& (data = {renderer: this.renderer, ...data}) | 
					
						
							| 
									
										
										
										
											2022-08-15 14:29:45 +03:00
										 |  |  | 		return object.parentCall(Page.prototype.clone, this, data, ...args) }, | 
					
						
							| 
									
										
										
										
											2022-08-04 11:00:21 +03:00
										 |  |  | }) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-10-06 22:48:09 +03:00
										 |  |  | //---------------------------------------------------------------------
 | 
					
						
							|  |  |  | // Markdown renderer...
 | 
					
						
							|  |  |  | // XXX EXPERIMENTAL...
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | var showdown = require('showdown') | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | var MarkdownPage = | 
					
						
							|  |  |  | module.MarkdownPage = | 
					
						
							|  |  |  | object.Constructor('MarkdownPage', Page, { | 
					
						
							|  |  |  | 	actions: { | 
					
						
							|  |  |  | 		...module.Page.prototype.actions, | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		html: true, | 
					
						
							|  |  |  | 	}, | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	markdown: new showdown.Converter(), | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	get html(){ return async function(){ | 
					
						
							|  |  |  | 		return this.markdown.makeHtml(await this.raw) }.call(this) }, | 
					
						
							|  |  |  | 	set html(value){ | 
					
						
							|  |  |  | 		this.raw = this.markdown.makeMarkdown(value) }, | 
					
						
							|  |  |  | }) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // XXX HACK...
 | 
					
						
							|  |  |  | var Page = MarkdownPage | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-08-22 10:07:22 +03:00
										 |  |  | //---------------------------------------------------------------------
 | 
					
						
							| 
									
										
										
										
											2022-09-17 19:30:11 +03:00
										 |  |  | // Cached .text page...
 | 
					
						
							| 
									
										
										
										
											2022-08-22 10:07:22 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-08-25 11:28:01 +03:00
										 |  |  | var getCachedProp =  | 
					
						
							|  |  |  | function(obj, name){ | 
					
						
							| 
									
										
										
										
											2022-08-24 23:47:42 +03:00
										 |  |  | 	var that = obj | 
					
						
							|  |  |  | 	var value = obj.cache ? | 
					
						
							|  |  |  | 		obj.cache[name] | 
					
						
							|  |  |  | 		: object.parentProperty(CachedPage.prototype, name).get.call(obj) | 
					
						
							|  |  |  | 	value instanceof Promise | 
					
						
							|  |  |  | 		&& value.then(function(value){ | 
					
						
							|  |  |  | 			that.cache = {[name]: value} }) | 
					
						
							|  |  |  | 	return value } | 
					
						
							| 
									
										
										
										
											2022-08-25 11:28:01 +03:00
										 |  |  | var setCachedProp =  | 
					
						
							|  |  |  | function(obj, name, value){ | 
					
						
							| 
									
										
										
										
											2022-08-24 23:47:42 +03:00
										 |  |  | 	return object.parentProperty(CachedPage.prototype, name).set.call(obj, value) } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-08-22 10:07:22 +03:00
										 |  |  | // XXX this is good enough on the front-side to think about making the 
 | 
					
						
							|  |  |  | // 		cache persistent with a very large timeout (if set at all), but
 | 
					
						
							|  |  |  | // 		we are not tracking changes on the store-side...
 | 
					
						
							|  |  |  | var CachedPage = | 
					
						
							|  |  |  | module.CachedPage = | 
					
						
							|  |  |  | object.Constructor('CachedPage', Page, { | 
					
						
							| 
									
										
										
										
											2022-09-01 00:04:13 +03:00
										 |  |  | 	// Sets what to use for cache id...
 | 
					
						
							|  |  |  | 	//
 | 
					
						
							|  |  |  | 	// Can be:
 | 
					
						
							|  |  |  | 	// 		'location' (default)
 | 
					
						
							|  |  |  | 	// 		'path'
 | 
					
						
							|  |  |  | 	cache_id: 'location', | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-08-22 10:07:22 +03:00
										 |  |  | 	// NOTE: set this to null/undefined/0 to disable...
 | 
					
						
							|  |  |  | 	cache_timeout: '20m', | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-08-22 12:31:19 +03:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	// keep all the cache in one place -- .root
 | 
					
						
							|  |  |  | 	//__cachestore: undefined,
 | 
					
						
							|  |  |  | 	get cachestore(){ | 
					
						
							|  |  |  | 		return (this.root ?? this).__cachestore }, | 
					
						
							|  |  |  | 	set cachestore(value){ | 
					
						
							|  |  |  | 		;(this.root ?? this).__cachestore = value }, | 
					
						
							|  |  |  | 	 | 
					
						
							| 
									
										
										
										
											2022-08-22 10:07:22 +03:00
										 |  |  | 	get cache(){ | 
					
						
							| 
									
										
										
										
											2022-09-01 00:04:13 +03:00
										 |  |  | 		this.checkCache(this[this.cache_id]) | 
					
						
							|  |  |  | 		return ((this.cachestore ?? {})[this[this.cache_id]] ?? {}).value }, | 
					
						
							| 
									
										
										
										
											2022-08-22 19:23:06 +03:00
										 |  |  | 	// XXX check * paths for matches...
 | 
					
						
							| 
									
										
										
										
											2022-08-22 10:07:22 +03:00
										 |  |  | 	set cache(value){ | 
					
						
							|  |  |  | 		if(this.cachestore === false  | 
					
						
							|  |  |  | 				|| this.cache == value){ | 
					
						
							|  |  |  | 			return } | 
					
						
							| 
									
										
										
										
											2022-09-01 00:04:13 +03:00
										 |  |  | 		var id = this[this.cache_id ?? 'location'] | 
					
						
							| 
									
										
										
										
											2022-08-22 19:23:06 +03:00
										 |  |  | 		// clear...
 | 
					
						
							| 
									
										
										
										
											2022-08-22 10:07:22 +03:00
										 |  |  | 		if(value == null){ | 
					
						
							| 
									
										
										
										
											2022-09-01 00:04:13 +03:00
										 |  |  | 			delete (this.cachestore ?? {})[id] | 
					
						
							| 
									
										
										
										
											2022-08-22 19:23:06 +03:00
										 |  |  | 		// set...
 | 
					
						
							| 
									
										
										
										
											2022-08-22 10:07:22 +03:00
										 |  |  | 		} else { | 
					
						
							| 
									
										
										
										
											2022-09-01 00:04:13 +03:00
										 |  |  | 			var prev = ((this.cachestore = this.cachestore ?? {})[id] ?? {}).value ?? {} | 
					
						
							|  |  |  | 			;(this.cachestore = this.cachestore ?? {})[id] = { | 
					
						
							| 
									
										
										
										
											2022-08-22 10:07:22 +03:00
										 |  |  | 				created: Date.now(), | 
					
						
							|  |  |  | 				// XXX
 | 
					
						
							|  |  |  | 				valid: undefined, | 
					
						
							| 
									
										
										
										
											2022-08-22 19:23:06 +03:00
										 |  |  | 				value: { | 
					
						
							|  |  |  | 					...prev,  | 
					
						
							|  |  |  | 					...value, | 
					
						
							|  |  |  | 				}, | 
					
						
							| 
									
										
										
										
											2022-08-22 10:07:22 +03:00
										 |  |  | 			} }  | 
					
						
							|  |  |  | 		// clear depended pages from cache...
 | 
					
						
							|  |  |  | 		for(var [key, deps] of Object.entries(this.dependencies)){ | 
					
						
							| 
									
										
										
										
											2022-08-22 19:23:06 +03:00
										 |  |  | 			// XXX also check pattern paths...
 | 
					
						
							|  |  |  | 			// 		...the problem here is that it's getting probabilistic, 
 | 
					
						
							|  |  |  | 			// 		i.e. if we match * as a single path item then we might 
 | 
					
						
							|  |  |  | 			// 		miss creating a subtree (ex: /tree), while matching 
 | 
					
						
							|  |  |  | 			// 		/* to anything will give us lots of false positives...
 | 
					
						
							| 
									
										
										
										
											2022-09-01 00:04:13 +03:00
										 |  |  | 			if(key != id && deps.has(id)){ | 
					
						
							| 
									
										
										
										
											2022-08-22 10:07:22 +03:00
										 |  |  | 				delete this.cachestore[key] } } }, | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-08-22 13:24:26 +03:00
										 |  |  | 	checkCache: function(...paths){ | 
					
						
							| 
									
										
										
										
											2022-08-22 10:07:22 +03:00
										 |  |  | 		if(!this.cache_timeout || !this.cachestore){ | 
					
						
							|  |  |  | 			return this } | 
					
						
							|  |  |  | 		paths = paths.length == 0 ? | 
					
						
							|  |  |  | 			Object.keys(this.cachestore) | 
					
						
							|  |  |  | 			: paths | 
					
						
							|  |  |  | 		for(var path of paths){ | 
					
						
							|  |  |  | 			var {created, valid, value} = this.cachestore[path] ?? {} | 
					
						
							|  |  |  | 			if(value){ | 
					
						
							|  |  |  | 				var now = Date.now() | 
					
						
							|  |  |  | 				valid = valid  | 
					
						
							|  |  |  | 					?? Date.str2ms(this.cache_timeout) | 
					
						
							|  |  |  | 				// drop cache...
 | 
					
						
							|  |  |  | 				if(now > created + valid){ | 
					
						
							|  |  |  | 					//console.log('CACHE: DROP:', this.path)
 | 
					
						
							|  |  |  | 					delete this.cachestore[path] } } } | 
					
						
							|  |  |  | 		return this }, | 
					
						
							| 
									
										
										
										
											2022-08-22 19:23:06 +03:00
										 |  |  | 	clearCache: function(...paths){ | 
					
						
							|  |  |  | 		if(this.cachestore){ | 
					
						
							|  |  |  | 			if(arguments.length == 0){ | 
					
						
							|  |  |  | 				this.cachestore = null  | 
					
						
							|  |  |  | 			} else { | 
					
						
							|  |  |  | 				for(var path of paths){ | 
					
						
							|  |  |  | 					delete this.cachestore[path] } } } | 
					
						
							|  |  |  | 		return this }, | 
					
						
							| 
									
										
										
										
											2022-08-22 10:07:22 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-08-22 13:24:26 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-08-22 10:07:22 +03:00
										 |  |  | 	__update__: function(){ | 
					
						
							|  |  |  | 		this.cache = null | 
					
						
							|  |  |  | 		return object.parentCall(CachedPage.prototype.__update__, this, ...arguments) }, | 
					
						
							|  |  |  | 	__delete__: function(){ | 
					
						
							|  |  |  | 		this.cache = null | 
					
						
							|  |  |  | 		return object.parentCall(CachedPage.prototype.__delete__, this, ...arguments) }, | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-08-24 23:47:42 +03:00
										 |  |  | 	/* XXX do we need to cache .raw??? | 
					
						
							|  |  |  | 	//		...yes this makes things marginally faster but essentially 
 | 
					
						
							|  |  |  | 	//		copies the db into memory...
 | 
					
						
							|  |  |  | 	get raw(){ | 
					
						
							|  |  |  | 		return getCachedProp(this, 'raw') }, | 
					
						
							|  |  |  | 	set raw(value){ | 
					
						
							|  |  |  | 		return setCachedProp(this, 'raw', value) }, | 
					
						
							|  |  |  | 	//*/
 | 
					
						
							| 
									
										
										
										
											2022-08-22 10:07:22 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-08-24 23:47:42 +03:00
										 |  |  | 	get text(){ | 
					
						
							|  |  |  | 		return getCachedProp(this, 'text') }, | 
					
						
							| 
									
										
										
										
											2022-08-22 10:07:22 +03:00
										 |  |  | 	set text(value){ | 
					
						
							| 
									
										
										
										
											2022-08-24 23:47:42 +03:00
										 |  |  | 		return setCachedProp(this, 'text', value) }, | 
					
						
							| 
									
										
										
										
											2022-08-22 10:07:22 +03:00
										 |  |  | }) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-08-06 11:09:25 +03:00
										 |  |  | //---------------------------------------------------------------------
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-11-29 20:22:46 +03:00
										 |  |  | var toc = require('./dom/toc') | 
					
						
							| 
									
										
										
										
											2022-08-10 11:42:31 +03:00
										 |  |  | var wikiword = require('./dom/wikiword') | 
					
						
							| 
									
										
										
										
											2022-11-01 01:56:22 +03:00
										 |  |  | //var textarea = require('./dom/textarea')
 | 
					
						
							| 
									
										
										
										
											2022-08-10 11:42:31 +03:00
										 |  |  | 
 | 
					
						
							|  |  |  | var pWikiPageElement = | 
					
						
							|  |  |  | module.pWikiPageElement =  | 
					
						
							| 
									
										
										
										
											2022-08-24 23:13:24 +03:00
										 |  |  | // XXX CACHE...
 | 
					
						
							| 
									
										
										
										
											2022-08-22 10:07:22 +03:00
										 |  |  | object.Constructor('pWikiPageElement', CachedPage, { | 
					
						
							| 
									
										
										
										
											2022-08-24 23:13:24 +03:00
										 |  |  | /*/ | 
					
						
							|  |  |  | object.Constructor('pWikiPageElement', Page, { | 
					
						
							| 
									
										
										
										
											2022-08-22 10:07:22 +03:00
										 |  |  | //*/
 | 
					
						
							| 
									
										
										
										
											2022-08-06 11:09:25 +03:00
										 |  |  | 	dom: undefined, | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-08-11 10:39:55 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-08-10 11:42:31 +03:00
										 |  |  | 	domFilters: { | 
					
						
							| 
									
										
										
										
											2022-11-29 20:22:46 +03:00
										 |  |  | 		toc: toc.makeToc, | 
					
						
							| 
									
										
										
										
											2022-08-10 11:42:31 +03:00
										 |  |  | 		// XXX see Page.filters.wikiword for notes...
 | 
					
						
							|  |  |  | 		wikiword: wikiword.wikiWordText, | 
					
						
							| 
									
										
										
										
											2022-11-01 01:56:22 +03:00
										 |  |  | 		//textarea: textarea.setupTextarea,
 | 
					
						
							| 
									
										
										
										
											2022-08-08 12:29:02 +03:00
										 |  |  | 	}, | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-08-24 23:13:24 +03:00
										 |  |  | 	// XXX CACHE
 | 
					
						
							| 
									
										
										
										
											2022-08-22 10:07:22 +03:00
										 |  |  | 	__clone_constructor__: CachedPage, | 
					
						
							| 
									
										
										
										
											2022-08-24 23:13:24 +03:00
										 |  |  | 	/*/ | 
					
						
							|  |  |  | 	__clone_constructor__: Page, | 
					
						
							|  |  |  | 	//*/
 | 
					
						
							| 
									
										
										
										
											2022-08-12 01:38:32 +03:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	__clone_proto: undefined, | 
					
						
							|  |  |  | 	get __clone_proto__(){ | 
					
						
							|  |  |  | 		return (this.__clone_proto = this.__clone_proto  | 
					
						
							|  |  |  | 			?? this.__clone_constructor__('/', '/', this.store)) }, | 
					
						
							|  |  |  | 	set __clone_proto__(value){ | 
					
						
							|  |  |  | 		this.__clone_proto = value }, | 
					
						
							|  |  |  | 	 | 
					
						
							| 
									
										
										
										
											2022-09-17 17:13:23 +03:00
										 |  |  | 	actions: { | 
					
						
							| 
									
										
										
										
											2022-09-02 14:58:45 +03:00
										 |  |  | 		...CachedPage.prototype.actions, | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-09-17 17:13:23 +03:00
										 |  |  | 		hash: true, | 
					
						
							|  |  |  | 	}, | 
					
						
							| 
									
										
										
										
											2022-09-02 14:58:45 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-12-02 02:43:36 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-08-11 10:39:55 +03:00
										 |  |  | 	// NOTE: setting location will reset .hash set it directly via either
 | 
					
						
							|  |  |  | 	// 		one of:
 | 
					
						
							|  |  |  | 	// 			.location = [path, hash]
 | 
					
						
							|  |  |  | 	// 			.location = 'path#hash'
 | 
					
						
							|  |  |  | 	hash: undefined, | 
					
						
							|  |  |  | 	// NOTE: getting .location will not return the hash, so as not to force
 | 
					
						
							|  |  |  | 	// 		the user to parse it out each time.
 | 
					
						
							|  |  |  | 	get location(){ | 
					
						
							|  |  |  | 		return object.parentProperty(pWikiPageElement.prototype, 'location') | 
					
						
							|  |  |  | 			.get.call(this) }, | 
					
						
							|  |  |  | 	set location(value){ | 
					
						
							|  |  |  | 		var [value, hash] =  | 
					
						
							|  |  |  | 			// .location = [path, hash]
 | 
					
						
							|  |  |  | 			value instanceof Array ? | 
					
						
							|  |  |  | 				value | 
					
						
							|  |  |  | 			// .location = '<path>#<hash>'
 | 
					
						
							|  |  |  | 			: value.includes('#') ? | 
					
						
							|  |  |  | 				value.split('#') | 
					
						
							|  |  |  | 			// no hash is given...
 | 
					
						
							|  |  |  | 			: [value, undefined] | 
					
						
							|  |  |  | 		this.hash = hash | 
					
						
							|  |  |  | 		object.parentProperty(pWikiPageElement.prototype, 'location') | 
					
						
							|  |  |  | 			.set.call(this, value) }, | 
					
						
							| 
									
										
										
										
											2022-08-08 23:04:42 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-08-08 12:29:02 +03:00
										 |  |  | 	// events...
 | 
					
						
							|  |  |  | 	//
 | 
					
						
							| 
									
										
										
										
											2022-08-10 11:42:31 +03:00
										 |  |  | 	__pWikiLoadedDOMEvent: new Event('pwikiloaded'), | 
					
						
							| 
									
										
										
										
											2022-10-28 14:17:37 +03:00
										 |  |  | 	onLoad: types.event.PureEvent('onLoad', function(){ | 
					
						
							| 
									
										
										
										
											2022-08-10 11:42:31 +03:00
										 |  |  | 		this.dom.dispatchEvent(this.__pWikiLoadedDOMEvent) }), | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-08-22 10:07:22 +03:00
										 |  |  | 	// XXX CACHE...
 | 
					
						
							| 
									
										
										
										
											2022-09-05 00:57:42 +03:00
										 |  |  | 	__last_refresh_location: undefined, | 
					
						
							| 
									
										
										
										
											2022-11-29 20:49:38 +03:00
										 |  |  | 	refresh: types.event.Event('refresh',  | 
					
						
							|  |  |  | 		async function(full=false){ | 
					
						
							|  |  |  | 			// drop cache if re-refreshing or when full refresh requested...
 | 
					
						
							|  |  |  | 			// XXX CACHE...
 | 
					
						
							|  |  |  | 			;(full | 
					
						
							|  |  |  | 					|| this.__last_refresh_location == this.location)	 | 
					
						
							|  |  |  | 				&& this.cache  | 
					
						
							|  |  |  | 				&& (this.cache = null) | 
					
						
							|  |  |  | 			this.__last_refresh_location = this.location | 
					
						
							|  |  |  | 			var dom = this.dom | 
					
						
							|  |  |  | 			dom.innerHTML = await this.text  | 
					
						
							|  |  |  | 			for(var filter of Object.values(this.domFilters)){ | 
					
						
							|  |  |  | 				filter | 
					
						
							|  |  |  | 					&& filter.call(this, dom) } | 
					
						
							|  |  |  | 			this.trigger('onLoad') | 
					
						
							|  |  |  | 			return this }), | 
					
						
							| 
									
										
										
										
											2022-08-10 11:42:31 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-08-11 10:39:55 +03:00
										 |  |  | 	// handle dom as first argument...
 | 
					
						
							| 
									
										
										
										
											2022-08-10 11:42:31 +03:00
										 |  |  | 	__init__: function(dom, ...args){ | 
					
						
							| 
									
										
										
										
											2022-08-11 23:56:43 +03:00
										 |  |  | 		if(typeof(Element) != 'undefined'){ | 
					
						
							|  |  |  | 			if(dom instanceof Element){ | 
					
						
							|  |  |  | 				this.dom = dom | 
					
						
							|  |  |  | 			} else { | 
					
						
							|  |  |  | 				args.unshift(dom) } } | 
					
						
							| 
									
										
										
										
											2022-08-10 11:42:31 +03:00
										 |  |  | 		return object.parentCall(pWikiPageElement.prototype.__init__, this, ...args) }, | 
					
						
							| 
									
										
										
										
											2022-08-06 11:09:25 +03:00
										 |  |  | }) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-08-04 11:00:21 +03:00
										 |  |  | //---------------------------------------------------------------------
 | 
					
						
							| 
									
										
										
										
											2022-08-04 14:29:25 +03:00
										 |  |  | // System pages/actions...
 | 
					
						
							| 
									
										
										
										
											2022-08-22 00:30:14 +03:00
										 |  |  | // XXX move this to a more appropriate module...
 | 
					
						
							| 
									
										
										
										
											2022-08-04 14:29:25 +03:00
										 |  |  | 
 | 
					
						
							|  |  |  | var System =  | 
					
						
							|  |  |  | module.System = { | 
					
						
							|  |  |  | 	// base templates...
 | 
					
						
							|  |  |  | 	//
 | 
					
						
							| 
									
										
										
										
											2022-08-05 18:21:18 +03:00
										 |  |  | 	// These are used to control how a page is rendered. 
 | 
					
						
							|  |  |  | 	//
 | 
					
						
							|  |  |  | 	// pWiki has to have a template appended to any path, if one is not 
 | 
					
						
							| 
									
										
										
										
											2022-08-17 23:38:24 +03:00
										 |  |  | 	// given then "_view" is used internally.
 | 
					
						
							| 
									
										
										
										
											2022-08-05 18:21:18 +03:00
										 |  |  | 	//
 | 
					
						
							|  |  |  | 	// A template is rendered in the context of the parent page, e.g. 
 | 
					
						
							| 
									
										
										
										
											2022-08-17 23:38:24 +03:00
										 |  |  | 	// for /path/to/page, the actual rendered template is /path/to/page/_view
 | 
					
						
							| 
									
										
										
										
											2022-08-05 18:21:18 +03:00
										 |  |  | 	// and it is rendered from /path/to/page.
 | 
					
						
							|  |  |  | 	//
 | 
					
						
							|  |  |  | 	// A template is any page named starting with an underscore ("_") 
 | 
					
						
							|  |  |  | 	// thus it is not recommended to use underscores to start page names.
 | 
					
						
							|  |  |  | 	//
 | 
					
						
							|  |  |  | 	// The actual default template is controlled via <page>.PAGE_TEMPLATE
 | 
					
						
							|  |  |  | 	//
 | 
					
						
							|  |  |  | 	// Example:
 | 
					
						
							|  |  |  | 	// 		_list: {
 | 
					
						
							|  |  |  | 	//			text: '<macro src="." join="\n">- @source(.)</macro>' },
 | 
					
						
							|  |  |  | 	//
 | 
					
						
							| 
									
										
										
										
											2023-02-08 18:44:36 +03:00
										 |  |  | 	// XXX might be a good idea to add a history stack to the API (macros?)
 | 
					
						
							| 
									
										
										
										
											2022-08-14 23:54:02 +03:00
										 |  |  | 	// XXX all of these should support pattern pages...
 | 
					
						
							| 
									
										
										
										
											2022-08-04 19:47:08 +03:00
										 |  |  | 	_text: { | 
					
						
							| 
									
										
										
										
											2022-09-05 17:16:07 +03:00
										 |  |  | 		text: '@include(.:$ARGS isolated join="@source(file-separator)")' }, | 
					
						
							| 
									
										
										
										
											2022-08-17 23:38:24 +03:00
										 |  |  | 	_view: { | 
					
						
							| 
									
										
										
										
											2022-08-17 14:10:25 +03:00
										 |  |  | 		text: object.doc`
 | 
					
						
							| 
									
										
										
										
											2022-10-28 01:44:04 +03:00
										 |  |  | 			<style>@include(./Style)</style> | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-10-03 02:35:14 +03:00
										 |  |  | 			<slot pre/> | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-09-22 03:27:02 +03:00
										 |  |  | 			<slot header> | 
					
						
							| 
									
										
										
										
											2022-08-30 10:58:04 +03:00
										 |  |  | 				<a href="#/list">☰</a> | 
					
						
							| 
									
										
										
										
											2023-02-11 23:12:51 +03:00
										 |  |  | 				<!-- | 
					
						
							| 
									
										
										
										
											2023-02-08 14:56:41 +03:00
										 |  |  | 				<a href="javascript:history.back()">ᐊ</a> | 
					
						
							|  |  |  | 				<a href="javascript:history.foreward()">ᐅ</a> | 
					
						
							|  |  |  | 				<a href="#<slot parent>../:@arg(all)</slot>">ᐃ</a> | 
					
						
							| 
									
										
										
										
											2023-02-11 23:12:51 +03:00
										 |  |  | 				--> | 
					
						
							| 
									
										
										
										
											2023-02-08 14:56:41 +03:00
										 |  |  | 				<a href="javascript:history.back()">🡠</a> | 
					
						
							|  |  |  | 				<a href="javascript:history.foreward()">🡢</a> | 
					
						
							|  |  |  | 				<a href="#<slot parent>../:@arg(all)</slot>">🡡</a> | 
					
						
							|  |  |  | 				<!-- use css for spacing... --> | 
					
						
							|  |  |  | 				   | 
					
						
							| 
									
										
										
										
											2023-02-08 03:27:06 +03:00
										 |  |  | 				<!-- XXX make this editable + inherit args... --> | 
					
						
							| 
									
										
										
										
											2022-12-02 03:19:16 +03:00
										 |  |  | 				[<slot location>@source(./location/quote/!)</slot>] | 
					
						
							| 
									
										
										
										
											2023-02-08 14:56:41 +03:00
										 |  |  | 				<!-- use css for spacing... --> | 
					
						
							|  |  |  | 				   | 
					
						
							| 
									
										
										
										
											2022-09-19 00:18:23 +03:00
										 |  |  | 				<a href="javascript:refresh()">⟳</a> | 
					
						
							| 
									
										
										
										
											2022-11-02 14:45:31 +03:00
										 |  |  | 				<slot edit> | 
					
						
							|  |  |  | 					<a href="#@source(s ./path/!)/edit">✎</a> | 
					
						
							|  |  |  | 				</slot> | 
					
						
							| 
									
										
										
										
											2022-08-22 10:07:22 +03:00
										 |  |  | 			</slot> | 
					
						
							| 
									
										
										
										
											2022-08-17 14:10:25 +03:00
										 |  |  | 			<hr> | 
					
						
							| 
									
										
										
										
											2022-11-02 14:45:31 +03:00
										 |  |  | 			<slot content/> | 
					
						
							|  |  |  | 			<hr> | 
					
						
							|  |  |  | 			<slot footer/> | 
					
						
							|  |  |  | 			 | 
					
						
							|  |  |  | 			<!-- NOTE: this is not included directly to enable client code to  | 
					
						
							|  |  |  | 					set slots that are defined after the content... --> | 
					
						
							| 
									
										
										
										
											2022-10-03 02:35:14 +03:00
										 |  |  | 			<slot content> | 
					
						
							| 
									
										
										
										
											2022-12-02 03:19:16 +03:00
										 |  |  | 				<h1><slot title>@source(./title/quote/!)</slot></h1> | 
					
						
							| 
									
										
										
										
											2022-09-05 17:16:07 +03:00
										 |  |  | 				@include(.:$ARGS join="@source(file-separator)" recursive="") | 
					
						
							| 
									
										
										
										
											2022-12-12 22:46:11 +03:00
										 |  |  | 			</slot>` }, | 
					
						
							| 
									
										
										
										
											2022-08-14 23:54:02 +03:00
										 |  |  | 	// XXX add join...
 | 
					
						
							| 
									
										
										
										
											2022-08-05 12:46:00 +03:00
										 |  |  | 	_raw: { | 
					
						
							|  |  |  | 		text: '@quote(.)' }, | 
					
						
							| 
									
										
										
										
											2022-08-05 02:47:31 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-08-14 02:08:27 +03:00
										 |  |  | 	// XXX not sure if this is the right way to go...
 | 
					
						
							|  |  |  | 	_code: { | 
					
						
							| 
									
										
										
										
											2022-08-14 23:54:02 +03:00
										 |  |  | 		text:  | 
					
						
							|  |  |  | 			'<macro src="." join="@source(file-separator)">' | 
					
						
							|  |  |  | 				+'<pre wikiwords="no"><quote filter="quote-tags" src="."/></pre>'  | 
					
						
							|  |  |  | 			+'</macro>'}, | 
					
						
							| 
									
										
										
										
											2022-08-17 23:38:24 +03:00
										 |  |  | 	/* XXX can we reuse _view here??? | 
					
						
							|  |  |  | 	_edit: { | 
					
						
							|  |  |  | 		text:  | 
					
						
							|  |  |  | 			'@include(PageTemplate)' | 
					
						
							| 
									
										
										
										
											2022-09-22 03:27:02 +03:00
										 |  |  | 			+'<slot header>@source(./path)</slot>' | 
					
						
							|  |  |  | 			+'<slot content>' | 
					
						
							| 
									
										
										
										
											2022-08-17 23:38:24 +03:00
										 |  |  | 				+'<macro src="." join="@source(file-separator)">' | 
					
						
							|  |  |  | 					+'<pre class="editor" ' | 
					
						
							|  |  |  | 							+'wikiwords="no" ' | 
					
						
							|  |  |  | 							+'contenteditable ' | 
					
						
							| 
									
										
										
										
											2022-09-19 00:18:23 +03:00
										 |  |  | 							+'oninput="saveLiveContent(\'@source(./path)\', this.innerText)">' | 
					
						
							| 
									
										
										
										
											2022-08-17 23:38:24 +03:00
										 |  |  | 						+'<quote filter="quote-tags" src="."/>' | 
					
						
							|  |  |  | 					+'</pre>'  | 
					
						
							|  |  |  | 				+'</macro>' | 
					
						
							|  |  |  | 			+'</slot>'}, | 
					
						
							|  |  |  | 	/*/ | 
					
						
							| 
									
										
										
										
											2022-08-15 14:29:45 +03:00
										 |  |  | 	_edit: { | 
					
						
							| 
									
										
										
										
											2022-08-14 03:00:06 +03:00
										 |  |  | 		text:  | 
					
						
							| 
									
										
										
										
											2022-12-02 03:19:16 +03:00
										 |  |  | 			'@source(./path/quote/!)' | 
					
						
							| 
									
										
										
										
											2022-08-17 14:10:25 +03:00
										 |  |  | 			+'<hr>' | 
					
						
							|  |  |  | 			+'<macro src="." join="@source(file-separator)">' | 
					
						
							| 
									
										
										
										
											2022-09-05 00:57:42 +03:00
										 |  |  | 				+'<h1 ' | 
					
						
							| 
									
										
										
										
											2022-10-30 14:26:35 +03:00
										 |  |  | 						+'wikiwords="no" ' | 
					
						
							| 
									
										
										
										
											2022-09-05 00:57:42 +03:00
										 |  |  | 						+'contenteditable ' | 
					
						
							|  |  |  | 						// XXX need to make this savable...
 | 
					
						
							| 
									
										
										
										
											2022-12-02 02:43:36 +03:00
										 |  |  | 						+'oninput="saveContent(\'@source(s ./path)/name\', this.innerText)">'  | 
					
						
							|  |  |  | 					+'@source(./title/quote)' | 
					
						
							| 
									
										
										
										
											2022-09-05 00:57:42 +03:00
										 |  |  | 				+'</h1>' | 
					
						
							| 
									
										
										
										
											2022-08-14 23:54:02 +03:00
										 |  |  | 				+'<pre class="editor" ' | 
					
						
							|  |  |  | 						+'wikiwords="no" ' | 
					
						
							|  |  |  | 						+'contenteditable ' | 
					
						
							| 
									
										
										
										
											2022-09-25 17:19:56 +03:00
										 |  |  | 						+'oninput="saveLiveContent(\'@source(s ./path)\', this.innerText)">' | 
					
						
							| 
									
										
										
										
											2022-08-14 23:54:02 +03:00
										 |  |  | 					+'<quote filter="quote-tags" src="."/>' | 
					
						
							|  |  |  | 				+'</pre>'  | 
					
						
							|  |  |  | 			+'</macro>'}, | 
					
						
							| 
									
										
										
										
											2022-08-17 23:38:24 +03:00
										 |  |  | 	edit: { | 
					
						
							| 
									
										
										
										
											2022-09-22 02:52:14 +03:00
										 |  |  | 		// XXX not sure if we should use .title or .name here...
 | 
					
						
							| 
									
										
										
										
											2022-08-22 00:30:14 +03:00
										 |  |  | 		text: object.doc`
 | 
					
						
							| 
									
										
										
										
											2022-11-02 15:06:43 +03:00
										 |  |  | 			<macro titleeditor> | 
					
						
							|  |  |  | 				<h1> | 
					
						
							|  |  |  | 					<span class="title-editor" | 
					
						
							|  |  |  | 							wikiwords="no" | 
					
						
							|  |  |  | 							contenteditable  | 
					
						
							| 
									
										
										
										
											2023-02-24 18:19:47 +03:00
										 |  |  | 							oninput="saveContent('@source(s ./path)/title', this.innerText)"> | 
					
						
							| 
									
										
										
										
											2022-12-02 02:43:36 +03:00
										 |  |  | 						@source(./title/quote) | 
					
						
							| 
									
										
										
										
											2022-11-02 15:06:43 +03:00
										 |  |  | 					</span> | 
					
						
							| 
									
										
										
										
											2023-02-20 02:21:22 +03:00
										 |  |  | 					@macro(src="."  | 
					
						
							|  |  |  | 						strict  | 
					
						
							|  |  |  | 						else='<span class="new-page-indicator">new</sup>') | 
					
						
							| 
									
										
										
										
											2022-11-02 15:06:43 +03:00
										 |  |  | 				</h1> | 
					
						
							|  |  |  | 			</macro> | 
					
						
							|  |  |  | 			<macro texteditor> | 
					
						
							|  |  |  | 				<pre class="editor" | 
					
						
							|  |  |  | 						wikiwords="no" | 
					
						
							|  |  |  | 						contenteditable | 
					
						
							| 
									
										
										
										
											2023-02-24 18:19:47 +03:00
										 |  |  | 						oninput="saveLiveContent('@source(s ./path)', this.innerText)" | 
					
						
							| 
									
										
										
										
											2023-02-17 18:55:38 +03:00
										 |  |  | 					><quote  | 
					
						
							|  |  |  | 						filter="quote-tags"  | 
					
						
							|  |  |  | 						src="." | 
					
						
							| 
									
										
										
										
											2023-02-24 18:19:47 +03:00
										 |  |  | 						else="@source('@arg(template .)')" | 
					
						
							|  |  |  | 						<!--else="@source('@arg(template @slot(editor-template .))')"--> | 
					
						
							| 
									
										
										
										
											2023-02-17 18:55:38 +03:00
										 |  |  | 					/></pre>  | 
					
						
							| 
									
										
										
										
											2022-11-02 15:06:43 +03:00
										 |  |  | 			</macro> | 
					
						
							|  |  |  | 			<macro editor join="@source(file-separator)"> | 
					
						
							| 
									
										
										
										
											2023-02-24 18:19:47 +03:00
										 |  |  | 				@macro(titleeditor .:$ARGS) | 
					
						
							|  |  |  | 				@macro(texteditor .:$ARGS) | 
					
						
							| 
									
										
										
										
											2022-11-02 15:06:43 +03:00
										 |  |  | 			</macro> | 
					
						
							|  |  |  | 			 | 
					
						
							| 
									
										
										
										
											2022-10-03 02:35:14 +03:00
										 |  |  | 			<slot pre> | 
					
						
							|  |  |  | 				<title>@source(../title) (edit)</title> | 
					
						
							|  |  |  | 			</slot> | 
					
						
							| 
									
										
										
										
											2022-09-22 03:27:02 +03:00
										 |  |  | 			<slot parent>../..</slot> | 
					
						
							| 
									
										
										
										
											2022-12-02 03:19:16 +03:00
										 |  |  | 			<slot location>@source(../location/quote/!)</slot> | 
					
						
							| 
									
										
										
										
											2022-11-02 14:45:31 +03:00
										 |  |  | 			<slot edit/> | 
					
						
							| 
									
										
										
										
											2022-09-22 03:27:02 +03:00
										 |  |  | 			<slot content> | 
					
						
							| 
									
										
										
										
											2023-02-24 18:19:47 +03:00
										 |  |  | 				<macro editor src="..:$ARGS" /> | 
					
						
							| 
									
										
										
										
											2022-10-29 01:40:27 +03:00
										 |  |  | 			</slot>`}, | 
					
						
							| 
									
										
										
										
											2022-11-02 14:45:31 +03:00
										 |  |  | 	// XXX EXPERIMENTAL...
 | 
					
						
							|  |  |  | 	ed: { | 
					
						
							|  |  |  | 		text: object.doc` @source(../ed-visual) `}, | 
					
						
							|  |  |  | 	'ed-visual': { | 
					
						
							|  |  |  | 		text: object.doc`
 | 
					
						
							|  |  |  | 			@load(./edit) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-11-02 15:06:43 +03:00
										 |  |  | 			<macro texteditor> | 
					
						
							| 
									
										
										
										
											2022-11-29 20:22:46 +03:00
										 |  |  | 				<toc></toc> | 
					
						
							| 
									
										
										
										
											2022-11-02 15:06:43 +03:00
										 |  |  | 				<div class="editor" | 
					
						
							|  |  |  | 						wikiwords="no" | 
					
						
							|  |  |  | 						contenteditable | 
					
						
							|  |  |  | 						class="native-editor" | 
					
						
							|  |  |  | 						oninput="saveLiveContent('@source(s ./path)/html', this.innerHTML)"> | 
					
						
							|  |  |  | 					@quote(./html) | 
					
						
							|  |  |  | 				</div> | 
					
						
							|  |  |  | 			</macro> | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			<!-- NOTE: we need to redefine this to make the overloaded  | 
					
						
							|  |  |  | 					texteditor macro visible... --> | 
					
						
							| 
									
										
										
										
											2022-11-02 14:45:31 +03:00
										 |  |  | 			<slot content> | 
					
						
							| 
									
										
										
										
											2022-11-02 15:06:43 +03:00
										 |  |  | 				<macro editor src=".."/> | 
					
						
							| 
									
										
										
										
											2022-11-02 14:45:31 +03:00
										 |  |  | 			</slot> | 
					
						
							|  |  |  | 			<slot footer> | 
					
						
							|  |  |  | 				<div style="text-align:right"> | 
					
						
							|  |  |  | 					<b>visual</b>  | 
					
						
							|  |  |  | 					| <a href="#../ed-text">text</a>  | 
					
						
							|  |  |  | 				</div> | 
					
						
							|  |  |  | 			</slot> `}, | 
					
						
							|  |  |  | 	'ed-text': { | 
					
						
							|  |  |  | 		text: object.doc`
 | 
					
						
							|  |  |  | 			@load(./edit) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-11-02 15:06:43 +03:00
										 |  |  | 			<macro texteditor> | 
					
						
							|  |  |  | 				<pre class="editor" | 
					
						
							|  |  |  | 						wikiwords="no" | 
					
						
							|  |  |  | 						contenteditable | 
					
						
							|  |  |  | 						class="native-editor" | 
					
						
							|  |  |  | 						oninput="saveLiveContent('@source(s ./path)', this.innerText)" | 
					
						
							|  |  |  | 					><quote filter="quote-tags" src="."/></pre>  | 
					
						
							|  |  |  | 			</macro> | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			<!-- NOTE: we need to redefine this to make the overloaded  | 
					
						
							|  |  |  | 					texteditor macro visible... --> | 
					
						
							| 
									
										
										
										
											2022-11-02 14:45:31 +03:00
										 |  |  | 			<slot content> | 
					
						
							| 
									
										
										
										
											2022-11-02 15:06:43 +03:00
										 |  |  | 				<macro editor src=".."/> | 
					
						
							| 
									
										
										
										
											2022-11-02 14:45:31 +03:00
										 |  |  | 			</slot> | 
					
						
							|  |  |  | 			<slot footer> | 
					
						
							|  |  |  | 				<div style="text-align:right"> | 
					
						
							|  |  |  | 					<a href="#../ed-visual">visual</a>  | 
					
						
							|  |  |  | 					| <b>text</b>  | 
					
						
							|  |  |  | 				</div> | 
					
						
							|  |  |  | 			</slot> `}, | 
					
						
							| 
									
										
										
										
											2022-10-29 01:40:27 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-08-15 14:29:45 +03:00
										 |  |  | 	// XXX debug...
 | 
					
						
							| 
									
										
										
										
											2022-09-18 20:45:55 +03:00
										 |  |  | 	_path: {text: '@source(./path/! join=" ")'}, | 
					
						
							|  |  |  | 	_location: {text: '@source(./location/! join=" ")'}, | 
					
						
							| 
									
										
										
										
											2022-08-15 14:29:45 +03:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	list: { | 
					
						
							| 
									
										
										
										
											2022-08-17 23:38:24 +03:00
										 |  |  | 		text: object.doc`
 | 
					
						
							| 
									
										
										
										
											2022-09-22 03:27:02 +03:00
										 |  |  | 			<slot header> | 
					
						
							| 
									
										
										
										
											2022-08-30 10:58:04 +03:00
										 |  |  | 				<a href="#/list">☰</a> | 
					
						
							| 
									
										
										
										
											2023-02-11 23:12:51 +03:00
										 |  |  | 				<a href="javascript:history.back()">🡠</a> | 
					
						
							|  |  |  | 				<a href="javascript:history.foreward()">🡢</a> | 
					
						
							|  |  |  | 				<a href="#<slot parent>../:@arg(all)</slot>">🡡</a> | 
					
						
							|  |  |  | 				<!-- | 
					
						
							| 
									
										
										
										
											2023-02-08 14:56:41 +03:00
										 |  |  | 				<a href="javascript:history.back()">ᐊ</a> | 
					
						
							|  |  |  | 				<a href="javascript:history.foreward()">ᐅ</a> | 
					
						
							|  |  |  | 				<a href="#@source(s ../../path)/list">ᐃ</a> | 
					
						
							| 
									
										
										
										
											2023-02-11 23:12:51 +03:00
										 |  |  | 				--> | 
					
						
							| 
									
										
										
										
											2023-02-08 14:56:41 +03:00
										 |  |  | 				   | 
					
						
							| 
									
										
										
										
											2022-08-17 23:38:24 +03:00
										 |  |  | 				@source(../path) | 
					
						
							|  |  |  | 			</slot> | 
					
						
							| 
									
										
										
										
											2022-10-26 17:06:06 +03:00
										 |  |  | 			<macro src="../*:$ARGS" join="@source(line-separator)"> | 
					
						
							| 
									
										
										
										
											2022-11-01 01:56:22 +03:00
										 |  |  | 				@var(path "@source(s ./path)") | 
					
						
							| 
									
										
										
										
											2022-12-02 02:43:36 +03:00
										 |  |  | 				<a href="#@var(path)">@source(./name/quote)</a> | 
					
						
							| 
									
										
										
										
											2022-08-29 18:22:35 +03:00
										 |  |  | 				<sup> | 
					
						
							| 
									
										
										
										
											2022-08-21 23:07:47 +03:00
										 |  |  | 					<macro src="./isAction"> | 
					
						
							|  |  |  | 						a | 
					
						
							|  |  |  | 						<else> | 
					
						
							|  |  |  | 							<macro src="./isStore">s</macro> | 
					
						
							|  |  |  | 						</else> | 
					
						
							|  |  |  | 					</macro> | 
					
						
							| 
									
										
										
										
											2022-08-29 18:22:35 +03:00
										 |  |  | 				</sup> | 
					
						
							| 
									
										
										
										
											2022-11-01 01:56:22 +03:00
										 |  |  | 				(<a href="#@var(path)/list">@include(./*/length/!)</a>) | 
					
						
							| 
									
										
										
										
											2022-08-29 18:22:35 +03:00
										 |  |  | 				  | 
					
						
							| 
									
										
										
										
											2023-02-13 21:17:05 +03:00
										 |  |  | 				<a class="show-on-hover"  | 
					
						
							|  |  |  | 					href="javascript:pwiki.delete('@var(path)')" | 
					
						
							|  |  |  | 					>×</a> | 
					
						
							| 
									
										
										
										
											2022-08-17 23:38:24 +03:00
										 |  |  | 			</macro>` }, | 
					
						
							| 
									
										
										
										
											2022-08-15 14:29:45 +03:00
										 |  |  | 	// XXX this is really slow...
 | 
					
						
							| 
									
										
										
										
											2022-11-04 15:32:04 +03:00
										 |  |  | 	// XXX need to handle count/offset arguments correctly...
 | 
					
						
							|  |  |  | 	// 		...for this we'll need to be able to either:
 | 
					
						
							|  |  |  | 	// 			- count our own pages or 
 | 
					
						
							|  |  |  | 	// 			- keep a global count
 | 
					
						
							| 
									
										
										
										
											2022-11-05 01:49:39 +03:00
										 |  |  | 	// 		...with offset the issue is not solvable because we will not 
 | 
					
						
							|  |  |  | 	// 		see/count the children of skipped nodes -- the only way to 
 | 
					
						
							|  |  |  | 	// 		solve this is to completely handle offset in macro...
 | 
					
						
							| 
									
										
										
										
											2022-08-15 14:29:45 +03:00
										 |  |  | 	tree: { | 
					
						
							|  |  |  | 		text: object.doc`
 | 
					
						
							| 
									
										
										
										
											2022-09-22 03:27:02 +03:00
										 |  |  | 			<slot title/> | 
					
						
							| 
									
										
										
										
											2022-11-05 01:49:39 +03:00
										 |  |  | 			<!--@var(count "@(count)")--> | 
					
						
							| 
									
										
										
										
											2022-10-31 16:49:53 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-11-05 15:22:00 +03:00
										 |  |  | 			<macro tree src="../*:$ARGS"> | 
					
						
							| 
									
										
										
										
											2022-11-01 01:56:22 +03:00
										 |  |  | 				@var(path "@source(s ./path)") | 
					
						
							| 
									
										
										
										
											2022-10-31 16:49:53 +03:00
										 |  |  | 				<div> | 
					
						
							|  |  |  | 					<div class="item"> | 
					
						
							| 
									
										
										
										
											2023-02-20 05:38:55 +03:00
										 |  |  | 						<!-- XXX should we pass :all here???  | 
					
						
							|  |  |  | 								it messes up "visited" link state... --> | 
					
						
							| 
									
										
										
										
											2023-02-08 03:27:06 +03:00
										 |  |  | 						<a class="tree-page-title" href="#@var(path):@arg(all)">@source(./title/quote)</a> | 
					
						
							| 
									
										
										
										
											2022-10-31 16:49:53 +03:00
										 |  |  | 						<a class="show-on-hover" href="#@var(path)/info">🛈</a> | 
					
						
							|  |  |  | 						<a class="show-on-hover"  | 
					
						
							|  |  |  | 							href="javascript:pwiki.delete('@var(path)')" | 
					
						
							|  |  |  | 							>×</a> | 
					
						
							|  |  |  | 					</div> | 
					
						
							|  |  |  | 					<div style="padding-left: 30px"> | 
					
						
							| 
									
										
										
										
											2022-11-05 01:49:39 +03:00
										 |  |  | 						@macro(tree "./*:$ARGS:count=inherit") | 
					
						
							| 
									
										
										
										
											2022-10-31 16:49:53 +03:00
										 |  |  | 					</div> | 
					
						
							|  |  |  | 				</div> | 
					
						
							|  |  |  | 			</macro>` }, | 
					
						
							|  |  |  | 	/* XXX @var(..) vs. multiple @source(..) calls are not that different... | 
					
						
							|  |  |  | 	tree2: { | 
					
						
							|  |  |  | 		text: object.doc`
 | 
					
						
							|  |  |  | 			<slot title/> | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			<i>This is a comparison with [../tree] -- \\@var(..) vs direct macro call...</i><br><br> | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			<macro tree src="../*:$ARGS"> | 
					
						
							| 
									
										
										
										
											2022-09-01 00:04:13 +03:00
										 |  |  | 				<div> | 
					
						
							|  |  |  | 					<div class="item"> | 
					
						
							| 
									
										
										
										
											2022-10-10 18:44:00 +03:00
										 |  |  | 						<a class="tree-page-title" href="#@source(s ./path)">@source(./title)</a> | 
					
						
							| 
									
										
										
										
											2022-09-25 17:19:56 +03:00
										 |  |  | 						<a class="show-on-hover" href="#@source(s ./path)/info">🛈</a> | 
					
						
							| 
									
										
										
										
											2022-10-31 02:29:21 +03:00
										 |  |  | 						<a class="show-on-hover"  | 
					
						
							|  |  |  | 							href="javascript:pwiki.delete('@source(s ./path)')" | 
					
						
							|  |  |  | 							>×</a> | 
					
						
							| 
									
										
										
										
											2022-09-01 00:04:13 +03:00
										 |  |  | 					</div> | 
					
						
							| 
									
										
										
										
											2022-08-15 14:29:45 +03:00
										 |  |  | 					<div style="padding-left: 30px"> | 
					
						
							| 
									
										
										
										
											2022-10-31 16:49:53 +03:00
										 |  |  | 						@macro(tree "./*:$ARGS") | 
					
						
							| 
									
										
										
										
											2022-08-15 14:29:45 +03:00
										 |  |  | 					</div> | 
					
						
							|  |  |  | 				</div> | 
					
						
							|  |  |  | 			</macro>` }, | 
					
						
							| 
									
										
										
										
											2022-10-31 16:49:53 +03:00
										 |  |  | 	//*/
 | 
					
						
							| 
									
										
										
										
											2022-08-17 23:38:24 +03:00
										 |  |  | 	all: { | 
					
						
							| 
									
										
										
										
											2022-10-26 17:06:06 +03:00
										 |  |  | 		text: `@include("../**/path:$ARGS" join="@source(line-separator)")`}, | 
					
						
							| 
									
										
										
										
											2022-08-15 14:29:45 +03:00
										 |  |  | 	info: { | 
					
						
							|  |  |  | 		text: object.doc`
 | 
					
						
							| 
									
										
										
										
											2022-10-03 02:35:14 +03:00
										 |  |  | 			<slot pre> | 
					
						
							| 
									
										
										
										
											2022-12-02 02:43:36 +03:00
										 |  |  | 				<title>@source(../title/quote) (info)</title> | 
					
						
							| 
									
										
										
										
											2022-10-03 02:35:14 +03:00
										 |  |  | 			</slot> | 
					
						
							| 
									
										
										
										
											2022-10-02 21:47:21 +03:00
										 |  |  | 			<slot title> | 
					
						
							| 
									
										
										
										
											2022-12-02 02:43:36 +03:00
										 |  |  | 				<h1><a href="#..">@source(../title/quote)</a></h1> | 
					
						
							| 
									
										
										
										
											2022-10-02 21:47:21 +03:00
										 |  |  | 			</slot> | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-12-02 02:43:36 +03:00
										 |  |  | 			Path: [@source(../path/quote)] | 
					
						
							| 
									
										
										
										
											2022-10-02 21:47:21 +03:00
										 |  |  | 				(<a href="#../edit">edit</a>)<br> | 
					
						
							| 
									
										
										
										
											2023-02-20 02:21:22 +03:00
										 |  |  | 			<macro src=".." strict><else> | 
					
						
							|  |  |  | 				Resolved path: [/@source(../resolved/quote)]<br> | 
					
						
							|  |  |  | 			</else></macro> | 
					
						
							| 
									
										
										
										
											2022-12-02 02:43:36 +03:00
										 |  |  | 			Referrer: [@source(../referrer/quote)]<br> | 
					
						
							| 
									
										
										
										
											2022-09-08 01:56:55 +03:00
										 |  |  | 			Args: <args/><br> | 
					
						
							| 
									
										
										
										
											2022-08-21 23:07:47 +03:00
										 |  |  | 
 | 
					
						
							|  |  |  | 			type: @source(../type)<br> | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-10-27 02:36:14 +03:00
										 |  |  | 			tags:  | 
					
						
							|  |  |  | 				<macro name="list-tags" src="../tags"> | 
					
						
							|  |  |  | 					<a href="#/**/path:tags=@source(.)">@source(.)</a> | 
					
						
							|  |  |  | 				</macro><br> | 
					
						
							|  |  |  | 			related tags:  | 
					
						
							|  |  |  | 				<macro name="list-tags" src="../relatedTags"/><br> | 
					
						
							| 
									
										
										
										
											2022-10-26 17:06:06 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-08-17 23:38:24 +03:00
										 |  |  | 			ctime: @source(../ctime)<br> | 
					
						
							|  |  |  | 			mtime: @source(../mtime)<br> | 
					
						
							| 
									
										
										
										
											2022-08-21 23:07:47 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-02-20 02:21:22 +03:00
										 |  |  | 			<br> | 
					
						
							|  |  |  | 			Resolved text: | 
					
						
							| 
									
										
										
										
											2022-08-17 23:38:24 +03:00
										 |  |  | 			<hr> | 
					
						
							|  |  |  | 			<pre wikiwords="no"><quote filter="quote-tags" src=".."/></pre> ` }, | 
					
						
							| 
									
										
										
										
											2022-08-14 23:54:02 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-08-26 18:16:07 +03:00
										 |  |  | 	// XXX need to also be able to list things about each store...
 | 
					
						
							|  |  |  | 	stores: function(){ | 
					
						
							|  |  |  | 		return Object.keys(this.store.substores ?? {}) }, | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-10-26 19:54:22 +03:00
										 |  |  | 	// tags...
 | 
					
						
							|  |  |  | 	//
 | 
					
						
							|  |  |  | 	// XXX should these be actions???
 | 
					
						
							|  |  |  | 	// 		...actions do not yet support lists/generators...
 | 
					
						
							|  |  |  | 	tags: async function*(){ | 
					
						
							|  |  |  | 		yield* this.get('..').tags }, | 
					
						
							|  |  |  | 	allTags: async function*(){ | 
					
						
							|  |  |  | 		yield* Object.keys((await this.store.tags).tags) }, | 
					
						
							|  |  |  | 	relatedTags: async function*(){ | 
					
						
							|  |  |  | 		yield* this.store.relatedTags( | 
					
						
							|  |  |  | 			...((await this.args.tags) | 
					
						
							|  |  |  | 				?? this.get('..').tags | 
					
						
							|  |  |  | 				?? [])) }, | 
					
						
							| 
									
										
										
										
											2022-10-26 19:18:21 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-08-14 23:54:02 +03:00
										 |  |  | 	// page parts...
 | 
					
						
							|  |  |  | 	//
 | 
					
						
							|  |  |  | 	'line-separator': { text: '<br>' }, | 
					
						
							|  |  |  | 	'file-separator': { text: '<hr>' }, | 
					
						
							| 
									
										
										
										
											2022-08-05 18:21:18 +03:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	// base system pages...
 | 
					
						
							|  |  |  | 	//
 | 
					
						
							|  |  |  | 	// NOTE: these are last resort pages, preferably overloaded in /Templates.
 | 
					
						
							| 
									
										
										
										
											2022-08-26 18:16:07 +03:00
										 |  |  | 	//
 | 
					
						
							| 
									
										
										
										
											2022-11-19 04:26:13 +03:00
										 |  |  | 	ParseError: { | 
					
						
							|  |  |  | 		text: object.doc`
 | 
					
						
							|  |  |  | 			<slot title/> | 
					
						
							|  |  |  | 			<div class="error"> | 
					
						
							| 
									
										
										
										
											2022-11-20 02:14:50 +03:00
										 |  |  | 				<div class="msg" wikiwords="no">ParseError: @(msg "no message")</div> | 
					
						
							| 
									
										
										
										
											2022-12-02 02:43:36 +03:00
										 |  |  | 				Page: [@(path "@source(./path/quote)")] | 
					
						
							| 
									
										
										
										
											2022-11-19 04:26:13 +03:00
										 |  |  | 			</div> `,}, | 
					
						
							| 
									
										
										
										
											2022-08-05 02:47:31 +03:00
										 |  |  | 	RecursionError: { | 
					
						
							| 
									
										
										
										
											2022-12-02 02:43:36 +03:00
										 |  |  | 		text: 'RECURSION ERROR: @source(../path/quote)' }, | 
					
						
							| 
									
										
										
										
											2022-11-19 04:26:13 +03:00
										 |  |  | 	NotFoundError: { | 
					
						
							| 
									
										
										
										
											2022-11-03 23:48:53 +03:00
										 |  |  | 		//text: 'NOT FOUND ERROR: @source(./path)' },
 | 
					
						
							|  |  |  | 		text: object.doc`
 | 
					
						
							|  |  |  | 			<slot title/> | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			<p>NOT FOUND ERROR: @source(./path)</p> | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			<slot nested> | 
					
						
							|  |  |  | 				<div> | 
					
						
							|  |  |  | 					<b>Nested pages:</b><br> | 
					
						
							|  |  |  | 					<div style="padding-left: 30px"> | 
					
						
							| 
									
										
										
										
											2022-11-27 02:34:40 +03:00
										 |  |  | 						<macro src="./*:$ARGS" join="<br>" else="@slot(nested)"> | 
					
						
							| 
									
										
										
										
											2022-12-02 02:43:36 +03:00
										 |  |  | 							<a href="#@source(s ./path)">@source(./title/quote)</a> | 
					
						
							| 
									
										
										
										
											2022-11-03 23:48:53 +03:00
										 |  |  | 						</macro> | 
					
						
							|  |  |  | 					</div> | 
					
						
							|  |  |  | 				</div> | 
					
						
							|  |  |  | 			</slot>` }, | 
					
						
							| 
									
										
										
										
											2022-08-18 01:23:49 +03:00
										 |  |  | 	NotFoundTemplateError: { | 
					
						
							| 
									
										
										
										
											2022-12-02 02:43:36 +03:00
										 |  |  | 		text: 'NOT FOUND TEMPLATE ERROR: @source(../path/quote)' }, | 
					
						
							| 
									
										
										
										
											2022-08-04 11:00:21 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-08-15 14:29:45 +03:00
										 |  |  | 	DeletingPage: { | 
					
						
							| 
									
										
										
										
											2022-12-02 02:43:36 +03:00
										 |  |  | 		text: 'Deleting: @source(../path/quote)' }, | 
					
						
							| 
									
										
										
										
											2022-08-15 14:29:45 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-08-17 23:38:24 +03:00
										 |  |  | 	PageTemplate: { | 
					
						
							|  |  |  | 		text: object.doc`
 | 
					
						
							| 
									
										
										
										
											2022-12-02 02:43:36 +03:00
										 |  |  | 			<slot header>@source(./path/quote)/edit</slot> | 
					
						
							| 
									
										
										
										
											2022-08-17 23:38:24 +03:00
										 |  |  | 			<hr> | 
					
						
							| 
									
										
										
										
											2022-09-22 03:27:02 +03:00
										 |  |  | 			<slot content></slot> | 
					
						
							| 
									
										
										
										
											2022-08-17 23:38:24 +03:00
										 |  |  | 			<hr> | 
					
						
							| 
									
										
										
										
											2022-09-22 03:27:02 +03:00
										 |  |  | 			<slot footer></slot> ` }, | 
					
						
							| 
									
										
										
										
											2022-08-21 23:07:47 +03:00
										 |  |  | 	QuoteActionPage: { | 
					
						
							|  |  |  | 		text: '[ native code ]' }, | 
					
						
							| 
									
										
										
										
											2022-08-17 23:38:24 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-10-28 01:44:04 +03:00
										 |  |  | 	Style: { | 
					
						
							|  |  |  | 		text: object.doc`
 | 
					
						
							|  |  |  | 		` },
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-08-05 18:21:18 +03:00
										 |  |  | 	// page actions...
 | 
					
						
							|  |  |  | 	//
 | 
					
						
							| 
									
										
										
										
											2022-09-02 17:27:40 +03:00
										 |  |  | 	 | 
					
						
							| 
									
										
										
										
											2022-09-02 21:15:22 +03:00
										 |  |  | 	// XXX this does not work as energetic...
 | 
					
						
							|  |  |  | 	time: async function(){ | 
					
						
							| 
									
										
										
										
											2022-09-14 03:33:05 +03:00
										 |  |  | 		var t = Date.now() | 
					
						
							| 
									
										
										
										
											2022-11-23 03:21:18 +03:00
										 |  |  | 		var text = await this.get('../_text:$ARGS').text | 
					
						
							| 
									
										
										
										
											2022-09-14 03:33:05 +03:00
										 |  |  | 		var time = Date.now() - t | 
					
						
							|  |  |  | 		console.log('RENDER TIME:', time) | 
					
						
							|  |  |  | 		return object.doc`
 | 
					
						
							| 
									
										
										
										
											2022-09-22 03:27:02 +03:00
										 |  |  | 			<slot title/> | 
					
						
							| 
									
										
										
										
											2022-09-19 00:18:23 +03:00
										 |  |  | 			Time to render: ${time}ms <br> | 
					
						
							|  |  |  | 			<hr> | 
					
						
							|  |  |  | 			${text}`},
 | 
					
						
							| 
									
										
										
										
											2022-11-18 03:26:33 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-08-22 00:30:14 +03:00
										 |  |  | 	// XXX EXPERIMENTAL -- page types...
 | 
					
						
							| 
									
										
										
										
											2022-08-21 20:45:29 +03:00
										 |  |  | 	isAction: async function(){ | 
					
						
							| 
									
										
										
										
											2022-08-21 23:07:47 +03:00
										 |  |  | 		return await this.get('..').type == 'action' ? | 
					
						
							|  |  |  | 			'action' | 
					
						
							|  |  |  | 			: undefined }, | 
					
						
							|  |  |  | 	isStore: async function(){ | 
					
						
							|  |  |  | 		return await this.get('..').type == 'store' ? | 
					
						
							|  |  |  | 			'store' | 
					
						
							| 
									
										
										
										
											2022-08-21 20:45:29 +03:00
										 |  |  | 			: undefined }, | 
					
						
							| 
									
										
										
										
											2022-08-04 14:29:25 +03:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-10-31 16:49:53 +03:00
										 |  |  | 	/* XXX need a stable way to redirect after the action... | 
					
						
							|  |  |  | 	//		...not sure if these are needed vs. pwiki.delete(..) and friends...
 | 
					
						
							| 
									
										
										
										
											2022-08-04 14:29:25 +03:00
										 |  |  | 	// actions...
 | 
					
						
							|  |  |  | 	//
 | 
					
						
							| 
									
										
										
										
											2022-09-24 01:02:01 +03:00
										 |  |  | 	// XXX should ** be the default here...
 | 
					
						
							| 
									
										
										
										
											2022-08-04 14:29:25 +03:00
										 |  |  | 	delete: function(){ | 
					
						
							| 
									
										
										
										
											2022-08-15 14:29:45 +03:00
										 |  |  | 		var target = this.get('..') | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-08-21 23:07:47 +03:00
										 |  |  | 		console.log('DELETE:', target.path) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-09-24 03:30:23 +03:00
										 |  |  | 		target.isPattern ? | 
					
						
							|  |  |  | 			target.delete() | 
					
						
							|  |  |  | 			: target.delete('**') | 
					
						
							| 
									
										
										
										
											2022-08-15 14:29:45 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-10-19 01:09:41 +03:00
										 |  |  | 		// XXX
 | 
					
						
							|  |  |  | 		if(this.referrer == this.path){ | 
					
						
							|  |  |  | 			this.renderer.path = '..' | 
					
						
							|  |  |  | 			return '' } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-08-15 14:29:45 +03:00
										 |  |  | 		// redirect...
 | 
					
						
							| 
									
										
										
										
											2022-09-05 00:57:42 +03:00
										 |  |  | 		this.renderer | 
					
						
							|  |  |  | 			&& (this.renderer.location = this.referrer) | 
					
						
							| 
									
										
										
										
											2022-09-18 20:12:18 +03:00
										 |  |  | 			// XXX this should not be needed...
 | 
					
						
							| 
									
										
										
										
											2022-09-18 15:46:06 +03:00
										 |  |  | 			&& this.renderer.refresh() | 
					
						
							| 
									
										
										
										
											2022-09-18 20:12:18 +03:00
										 |  |  | 		// XXX returning undefined will stop the redirect...
 | 
					
						
							|  |  |  | 		return '' }, | 
					
						
							| 
									
										
										
										
											2022-09-19 00:18:23 +03:00
										 |  |  | 	// NOTE: this moves relative to the basedir and not relative to the 
 | 
					
						
							|  |  |  | 	// 		page...
 | 
					
						
							|  |  |  | 	move: async function(){ | 
					
						
							| 
									
										
										
										
											2022-09-05 00:57:42 +03:00
										 |  |  | 		var from = this.get('..') | 
					
						
							|  |  |  | 		// XXX this is ugly...
 | 
					
						
							|  |  |  | 		// 		...need to standardize how we get arguments when rendering....
 | 
					
						
							|  |  |  | 		var to = this.args.to  | 
					
						
							|  |  |  | 			|| (this.renderer || {args:{}}).args.to | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		console.log('MOVE:', from.path, to) | 
					
						
							| 
									
										
										
										
											2022-09-19 00:18:23 +03:00
										 |  |  | 
 | 
					
						
							|  |  |  | 		to | 
					
						
							| 
									
										
										
										
											2022-09-24 03:30:23 +03:00
										 |  |  | 			&& await (from.isPattern ? | 
					
						
							|  |  |  | 					from | 
					
						
							|  |  |  | 					: from.get('**')) | 
					
						
							|  |  |  | 				.move( | 
					
						
							|  |  |  | 					/^[\\\/]/.test(to[0]) ? | 
					
						
							|  |  |  | 						to | 
					
						
							|  |  |  | 						: pwpath.join('..', to)) | 
					
						
							| 
									
										
										
										
											2022-09-19 00:18:23 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-09-05 00:57:42 +03:00
										 |  |  | 		// redirect...
 | 
					
						
							|  |  |  | 		this.renderer | 
					
						
							| 
									
										
										
										
											2022-09-19 00:18:23 +03:00
										 |  |  | 			&& to | 
					
						
							|  |  |  | 			//&& (this.renderer.location = this.referrer)
 | 
					
						
							|  |  |  | 			&& (this.renderer.location = from.path) | 
					
						
							| 
									
										
										
										
											2022-09-18 20:12:18 +03:00
										 |  |  | 			// XXX this should not be needed...
 | 
					
						
							|  |  |  | 			&& this.renderer.refresh() | 
					
						
							| 
									
										
										
										
											2022-09-05 00:57:42 +03:00
										 |  |  | 		// XXX if we return undefined here this will not fully redirect, 
 | 
					
						
							|  |  |  | 		// 		keeping the move page open but setting the url to the 
 | 
					
						
							|  |  |  | 		// 		redirected page...
 | 
					
						
							|  |  |  | 		return '' }, | 
					
						
							| 
									
										
										
										
											2022-09-19 00:18:23 +03:00
										 |  |  | 	// XXX copy/...
 | 
					
						
							| 
									
										
										
										
											2022-10-31 16:49:53 +03:00
										 |  |  | 	//*/
 | 
					
						
							| 
									
										
										
										
											2022-08-21 12:31:04 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-08-04 14:29:25 +03:00
										 |  |  | 	// XXX System/sort
 | 
					
						
							|  |  |  | 	// XXX System/reverse
 | 
					
						
							| 
									
										
										
										
											2022-08-20 09:37:05 +03:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-09-22 03:27:02 +03:00
										 |  |  | var Templates =  | 
					
						
							|  |  |  | module.Templates = { | 
					
						
							|  |  |  | 	// XXX should this be in templates???
 | 
					
						
							|  |  |  | 	// XXX for some reason this does not list files...
 | 
					
						
							|  |  |  | 	FlatNotes: { | 
					
						
							|  |  |  | 		text: object.doc`
 | 
					
						
							| 
									
										
										
										
											2023-02-17 05:32:27 +03:00
										 |  |  | 		@var(editor_template FlatNotes/EmptyPage) | 
					
						
							| 
									
										
										
										
											2023-02-17 05:12:30 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-09-22 03:27:02 +03:00
										 |  |  | 		<slot title/> | 
					
						
							| 
									
										
										
										
											2023-02-17 05:32:27 +03:00
										 |  |  | 		<slot header><content/><a href="#./$NOW/edit:template=@var(editor_template)">🗎</a></slot> | 
					
						
							| 
									
										
										
										
											2023-02-17 05:12:30 +03:00
										 |  |  | 		<macro src="*:sort=-mtime:$ARGS" strict> | 
					
						
							| 
									
										
										
										
											2022-11-06 19:15:40 +03:00
										 |  |  | 			@var(path "@source(s ./path)") | 
					
						
							| 
									
										
										
										
											2022-09-22 03:27:02 +03:00
										 |  |  | 			<div class="item"> | 
					
						
							| 
									
										
										
										
											2023-02-17 05:32:27 +03:00
										 |  |  | 				<a href="#@var(path)/edit:template=@var(editor_template)">@source(./title/quote)</a> | 
					
						
							| 
									
										
										
										
											2022-11-06 19:15:40 +03:00
										 |  |  | 				<a class="show-on-hover" href="#@var(path)/info">🛈</a> | 
					
						
							|  |  |  | 				<a class="show-on-hover"  | 
					
						
							|  |  |  | 					href="javascript:pwiki.delete('@var(path)')" | 
					
						
							|  |  |  | 					>×</a> | 
					
						
							| 
									
										
										
										
											2022-09-22 03:27:02 +03:00
										 |  |  | 			</div> | 
					
						
							| 
									
										
										
										
											2023-02-17 05:12:30 +03:00
										 |  |  | 			<else> | 
					
						
							| 
									
										
										
										
											2023-02-17 05:32:27 +03:00
										 |  |  | 				<a href="#./$NOW/edit:template=@var(editor_template)" class="placeholder">Empty</a> | 
					
						
							| 
									
										
										
										
											2023-02-17 05:12:30 +03:00
										 |  |  | 			</else> | 
					
						
							| 
									
										
										
										
											2022-09-22 03:27:02 +03:00
										 |  |  | 		</macro>` }, | 
					
						
							| 
									
										
										
										
											2022-09-25 17:19:56 +03:00
										 |  |  | 	// XXX this is not resolved...
 | 
					
						
							| 
									
										
										
										
											2023-02-17 05:12:30 +03:00
										 |  |  | 	'FlatNotes/EmptyPage': {text: ' '}, | 
					
						
							| 
									
										
										
										
											2022-09-22 03:27:02 +03:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-08-20 09:37:05 +03:00
										 |  |  | var Test = | 
					
						
							|  |  |  | module.Test = { | 
					
						
							| 
									
										
										
										
											2022-09-09 19:18:09 +03:00
										 |  |  | 	// XXX do we support this???
 | 
					
						
							|  |  |  | 	//'list/action': function(){
 | 
					
						
							|  |  |  | 	//	return [...'abcdef'] },
 | 
					
						
							|  |  |  | 	'list/generator': function*(){ | 
					
						
							|  |  |  | 		yield* [...'abcdef'] }, | 
					
						
							|  |  |  | 	'list/static': { | 
					
						
							| 
									
										
										
										
											2022-08-20 09:37:05 +03:00
										 |  |  | 		text: [...'abcdef'] }, | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-09-10 02:26:10 +03:00
										 |  |  | 	// this is shown by most listers by adding an :all argument to the url...
 | 
					
						
							|  |  |  | 	'.hidden': { | 
					
						
							|  |  |  | 		text: 'Hidden page...' }, | 
					
						
							| 
									
										
										
										
											2022-09-11 08:52:38 +03:00
										 |  |  | 	'.hidden/subpage': { | 
					
						
							|  |  |  | 		text: 'visible subpage...' }, | 
					
						
							|  |  |  | 	'.hidden/.hidden': { | 
					
						
							|  |  |  | 		text: 'hidden subpage...' }, | 
					
						
							| 
									
										
										
										
											2022-09-10 02:26:10 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-08-20 09:37:05 +03:00
										 |  |  | 	slots: { | 
					
						
							| 
									
										
										
										
											2022-08-18 01:23:49 +03:00
										 |  |  | 		text: object.doc`
 | 
					
						
							|  |  |  | 			Sequential: | 
					
						
							|  |  |  | 			<slot name="sequential">unfilled</slot> | 
					
						
							|  |  |  | 			<slot name="sequential">filled</slot> | 
					
						
							|  |  |  | 			<slot name="sequential">refilled</slot>  | 
					
						
							|  |  |  | 			<br><br> | 
					
						
							|  |  |  | 			Nested: | 
					
						
							|  |  |  | 			<slot name="nested"> | 
					
						
							|  |  |  | 				unfilled | 
					
						
							|  |  |  | 				<slot name="nested"> | 
					
						
							|  |  |  | 					filled | 
					
						
							|  |  |  | 					<slot name="nested"> | 
					
						
							|  |  |  | 						refilled | 
					
						
							|  |  |  | 					</slot> | 
					
						
							|  |  |  | 				</slot> | 
					
						
							|  |  |  | 			</slot>  | 
					
						
							|  |  |  | 			<br><br> | 
					
						
							|  |  |  | 			Content: A B C: | 
					
						
							|  |  |  | 			<slot name="slot-content">A</slot> | 
					
						
							|  |  |  | 			<slot name="slot-content"><content/> B</slot> | 
					
						
							|  |  |  | 			<slot name="slot-conten"><content/> C</slot> | 
					
						
							|  |  |  | 			<br><br> | 
					
						
							| 
									
										
										
										
											2022-08-18 20:34:13 +03:00
										 |  |  | 			Nested content: A B C: | 
					
						
							|  |  |  | 			<slot name="nested-slot-content"> | 
					
						
							|  |  |  | 				A | 
					
						
							|  |  |  | 				<slot name="nested-slot-content"> | 
					
						
							|  |  |  | 					<content/> B | 
					
						
							|  |  |  | 					<slot name="nested-slot-content"> | 
					
						
							|  |  |  | 						<content/> C | 
					
						
							|  |  |  | 					</slot> | 
					
						
							|  |  |  | 				</slot> | 
					
						
							| 
									
										
										
										
											2022-08-19 13:13:17 +03:00
										 |  |  | 			</slot> | 
					
						
							|  |  |  | 			<br><br> | 
					
						
							|  |  |  | 			Mixed content: X A B C Z: | 
					
						
							|  |  |  | 			<slot name="mixed-slot-content"> | 
					
						
							|  |  |  | 				X | 
					
						
							|  |  |  | 			</slot> | 
					
						
							|  |  |  | 			<slot name="mixed-slot-content"> | 
					
						
							|  |  |  | 				<content/> A | 
					
						
							|  |  |  | 				<slot name="mixed-slot-content"> | 
					
						
							| 
									
										
										
										
											2022-08-18 01:23:49 +03:00
										 |  |  | 					<content/> B | 
					
						
							|  |  |  | 				</slot> | 
					
						
							| 
									
										
										
										
											2022-08-19 13:13:17 +03:00
										 |  |  | 				<slot name="mixed-slot-content"> | 
					
						
							|  |  |  | 					<content/> C | 
					
						
							|  |  |  | 				</slot> | 
					
						
							|  |  |  | 			</slot>  | 
					
						
							|  |  |  | 			<slot name="mixed-slot-content"> | 
					
						
							|  |  |  | 				<content/> Z | 
					
						
							| 
									
										
										
										
											2022-08-18 01:23:49 +03:00
										 |  |  | 			</slot> ` }, | 
					
						
							| 
									
										
										
										
											2022-08-21 01:28:29 +03:00
										 |  |  | 	macros: { | 
					
						
							|  |  |  | 		text: object.doc`
 | 
					
						
							|  |  |  | 			<macro name="list" join="<br>"> | 
					
						
							|  |  |  | 				- @include(./path) | 
					
						
							|  |  |  | 			</macro> | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			<macro name="list" src="/Test/*"/> | 
					
						
							|  |  |  | 			<br><br> | 
					
						
							|  |  |  | 			<macro name="list" src="/Test/*" join=",<br>"/> | 
					
						
							|  |  |  | 		`},
 | 
					
						
							| 
									
										
										
										
											2022-09-02 21:15:22 +03:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	Subtree: { | 
					
						
							|  |  |  | 		text: object.doc`
 | 
					
						
							|  |  |  | 			This is here to test the performance of macros:<br> | 
					
						
							|  |  |  | 				./list <br> | 
					
						
							|  |  |  | 				./tree <br> | 
					
						
							|  |  |  | 				./**/path <br> ` },
 | 
					
						
							| 
									
										
										
										
											2022-08-04 14:29:25 +03:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											2022-09-02 21:15:22 +03:00
										 |  |  | // Generate pages...
 | 
					
						
							|  |  |  | PAGES=100 | 
					
						
							|  |  |  | for(var i=0; i<PAGES; i++){ | 
					
						
							|  |  |  | 	Test['Subtree/Page'+i] = {text: 'page: '+i} } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-09-18 20:45:55 +03:00
										 |  |  | var Config = | 
					
						
							|  |  |  | module.Config = { | 
					
						
							| 
									
										
										
										
											2023-02-24 16:20:19 +03:00
										 |  |  | 	Import: { | 
					
						
							| 
									
										
										
										
											2023-02-24 18:19:47 +03:00
										 |  |  | 		text: '<input type="file" onchange="importData()" accept=".json, .pwiki">' }, | 
					
						
							| 
									
										
										
										
											2023-02-23 23:49:37 +03:00
										 |  |  | 	// XXX need an import button...
 | 
					
						
							| 
									
										
										
										
											2022-08-14 03:00:06 +03:00
										 |  |  | 	Export: { | 
					
						
							|  |  |  | 		text: '<button onclick="exportData()">Export</button>' }, | 
					
						
							|  |  |  | 	// XXX
 | 
					
						
							| 
									
										
										
										
											2022-08-14 03:10:24 +03:00
										 |  |  | 	Config: { | 
					
						
							| 
									
										
										
										
											2022-10-28 01:34:58 +03:00
										 |  |  | 		text: object.doc`{
 | 
					
						
							|  |  |  | 		}` },
 | 
					
						
							|  |  |  | 	Style: { | 
					
						
							|  |  |  | 		text: object.doc`
 | 
					
						
							|  |  |  | 		` },
 | 
					
						
							| 
									
										
										
										
											2022-08-14 03:00:06 +03:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-08-04 11:00:21 +03:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /********************************************************************** | 
					
						
							|  |  |  | * vim:set ts=4 sw=4 nowrap :                        */ return module }) |