| 
									
										
										
										
											2022-08-03 01:35:19 +03:00
										 |  |  | /********************************************************************** | 
					
						
							|  |  |  | *  | 
					
						
							|  |  |  | * | 
					
						
							|  |  |  | * | 
					
						
							|  |  |  | **********************************************************************/ | 
					
						
							|  |  |  | ((typeof define)[0]=='u'?function(f){module.exports=f(require)}:define) | 
					
						
							|  |  |  | (function(require){ var module={} // make module AMD/node compatible...
 | 
					
						
							|  |  |  | /*********************************************************************/ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | var types = require('ig-types') | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-09-25 19:22:32 +03:00
										 |  |  | //---------------------------------------------------------------------
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | var makeEncoder = function(name, chars){ | 
					
						
							|  |  |  | 	var pattern_attr = '__'+name+'_pattern' | 
					
						
							|  |  |  | 	return function(str){ | 
					
						
							|  |  |  | 		var pattern = this[pattern_attr] =  | 
					
						
							|  |  |  | 			this[pattern_attr]  | 
					
						
							|  |  |  | 				?? RegExp(`[${ | 
					
						
							|  |  |  | 					this[chars] | 
					
						
							|  |  |  | 						.replace(/\\/g, '\\\\') }]`, 'g')
 | 
					
						
							|  |  |  | 		return str | 
					
						
							|  |  |  | 			.replace(pattern, | 
					
						
							|  |  |  | 				function(s){  | 
					
						
							|  |  |  | 					return ('%'+s.charCodeAt().toString(16)).toUpperCase() }) } } | 
					
						
							|  |  |  | var makeDecoder = function(name, encode, chars){ | 
					
						
							|  |  |  | 	var pattern_attr = '__'+name+'_pattern' | 
					
						
							|  |  |  | 	return function(str){ | 
					
						
							|  |  |  | 		var pattern = this[pattern_attr] =  | 
					
						
							|  |  |  | 			this[pattern_attr]  | 
					
						
							|  |  |  | 				?? RegExp(`%(${ | 
					
						
							|  |  |  | 					this[encode](this[chars]) | 
					
						
							|  |  |  | 						.slice(1) | 
					
						
							|  |  |  | 						.replace(/%/g, '|') })`, 'gi')
 | 
					
						
							|  |  |  | 		return str | 
					
						
							|  |  |  | 			.replace(pattern, function(_, c){ | 
					
						
							|  |  |  | 				return String.fromCharCode('0x'+c) }) } } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-08-03 01:35:19 +03:00
										 |  |  | //---------------------------------------------------------------------
 | 
					
						
							|  |  |  | // Path...
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | module = { | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// Page returned when listing a path ending with '/'...
 | 
					
						
							|  |  |  | 	//
 | 
					
						
							|  |  |  | 	// If set to false treat dirs the same as pages (default)
 | 
					
						
							|  |  |  | 	//INDEX_PAGE: 'index',
 | 
					
						
							|  |  |  | 	INDEX_PAGE: false, | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// The page returned when getting the '/' path...
 | 
					
						
							|  |  |  | 	//
 | 
					
						
							|  |  |  | 	// NOTE: this is the same as .INDEX_PAGE but only for '/'
 | 
					
						
							|  |  |  | 	ROOT_PAGE: 'WikiHome', | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	ALTERNATIVE_PAGES: [ | 
					
						
							|  |  |  | 		'EmptyPage', | 
					
						
							| 
									
										
										
										
											2022-08-05 02:47:31 +03:00
										 |  |  | 		'NotFoundError', | 
					
						
							| 
									
										
										
										
											2022-08-03 01:35:19 +03:00
										 |  |  | 	], | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// Default alternate search locations...
 | 
					
						
							|  |  |  | 	//
 | 
					
						
							|  |  |  | 	// NOTE: if a path here is relative it is also searched relative to 
 | 
					
						
							|  |  |  | 	// 		the target path.
 | 
					
						
							|  |  |  | 	SEARCH_PATHS: [ | 
					
						
							| 
									
										
										
										
											2022-09-22 03:27:02 +03:00
										 |  |  | 		'.templates', | 
					
						
							| 
									
										
										
										
											2022-08-03 01:35:19 +03:00
										 |  |  | 	], | 
					
						
							| 
									
										
										
										
											2022-09-17 19:30:11 +03:00
										 |  |  | 	 | 
					
						
							|  |  |  | 	// System path...
 | 
					
						
							|  |  |  | 	//
 | 
					
						
							|  |  |  | 	// This acts the same as elements in .SEARCH_PATHS but should contain 
 | 
					
						
							|  |  |  | 	// all the default and fallback templates.
 | 
					
						
							| 
									
										
										
										
											2022-09-18 15:46:06 +03:00
										 |  |  | 	//
 | 
					
						
							|  |  |  | 	// NOTE: we can't use .pwiki here as it will be in conflict with the
 | 
					
						
							|  |  |  | 	// 		fs store's directory structure.
 | 
					
						
							|  |  |  | 	// 		XXX or can we?
 | 
					
						
							| 
									
										
										
										
											2022-09-17 19:30:11 +03:00
										 |  |  | 	SYSTEM_PATH: '/.system', | 
					
						
							| 
									
										
										
										
											2022-08-03 01:35:19 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-09-20 01:00:44 +03:00
										 |  |  | 	// XXX EXPERIMENTAL
 | 
					
						
							| 
									
										
										
										
											2022-09-25 19:22:32 +03:00
										 |  |  | 	 | 
					
						
							|  |  |  | 	ENCODED_PATH: '#:*%', | 
					
						
							|  |  |  | 	encode: makeEncoder('encode', 'ENCODED_PATH'), | 
					
						
							|  |  |  | 	decode: makeDecoder('decode', 'encode', 'ENCODED_PATH'), | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	ENCODED_ELEM: '#:*%\\/', | 
					
						
							|  |  |  | 	encodeElem: makeEncoder('encode_elem', 'ENCODED_ELEM'), | 
					
						
							|  |  |  | 	decodeElem: makeDecoder('decode_elem', 'encodeElem', 'ENCODED_ELEM'), | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// chars we keep in path as-is -- decode on normalize...
 | 
					
						
							|  |  |  | 	//
 | 
					
						
							|  |  |  | 	UNENCODED_PATH: '\'"', | 
					
						
							|  |  |  | 	quote: makeEncoder('quote', 'UNENCODED_PATH'), | 
					
						
							|  |  |  | 	unquote: makeDecoder('unquote', 'quote', 'UNENCODED_PATH'), | 
					
						
							| 
									
										
										
										
											2022-09-20 01:00:44 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-08-24 23:13:24 +03:00
										 |  |  | 	/*/ XXX NORMCACHE... | 
					
						
							|  |  |  | 	__normalized_cache_threshold: 100, | 
					
						
							|  |  |  | 	__normalized_cache_size: 4096, | 
					
						
							|  |  |  | 	__normalized_cache: undefined, | 
					
						
							|  |  |  | 	get _normalized_cache(){ | 
					
						
							|  |  |  | 		var norm = this.__normalized =  | 
					
						
							|  |  |  | 			this.__normalized  | 
					
						
							|  |  |  | 			?? new Set() | 
					
						
							|  |  |  | 		// trim to size...
 | 
					
						
							|  |  |  | 		var l = norm.size | 
					
						
							|  |  |  | 		var lim = this.__normalized_cache_size ?? 1000 | 
					
						
							|  |  |  | 		var t = this.__normalized_cache_threshold ?? 100 | 
					
						
							|  |  |  | 		if(l > lim){ | 
					
						
							|  |  |  | 			norm = this.__normalized = new Set([...norm].slice(Math.max(l - lim - t, t))) } | 
					
						
							|  |  |  | 		return norm }, | 
					
						
							|  |  |  | 	//*/
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-08-03 01:35:19 +03:00
										 |  |  | 	// Path utils...
 | 
					
						
							|  |  |  | 	//
 | 
					
						
							|  |  |  | 	// Path can be in one of two formats:
 | 
					
						
							|  |  |  | 	// 	string
 | 
					
						
							|  |  |  | 	// 	array
 | 
					
						
							|  |  |  | 	//
 | 
					
						
							|  |  |  | 	// NOTE: trailing/leading '/' are represented by '' at end/start of 
 | 
					
						
							|  |  |  | 	// 		path list...
 | 
					
						
							|  |  |  | 	normalize: function(path='.', format='auto'){ | 
					
						
							| 
									
										
										
										
											2022-08-24 23:13:24 +03:00
										 |  |  | 		/*/ XXX NORMCACHE... | 
					
						
							|  |  |  | 		if(typeof(path) == 'string'  | 
					
						
							|  |  |  | 				&& format != 'array'  | 
					
						
							|  |  |  | 				&& this._normalized_cache.has(path)){ | 
					
						
							| 
									
										
										
										
											2022-08-23 11:27:20 +03:00
										 |  |  | 			return path } | 
					
						
							|  |  |  | 		//*/
 | 
					
						
							| 
									
										
										
										
											2022-08-03 01:35:19 +03:00
										 |  |  | 		format = format == 'auto' ? | 
					
						
							|  |  |  | 			(path instanceof Array ? | 
					
						
							|  |  |  | 				'array' | 
					
						
							|  |  |  | 				: 'string') | 
					
						
							|  |  |  | 			: format | 
					
						
							|  |  |  | 		var root = path[0] == ''  | 
					
						
							|  |  |  | 			|| path[0] == '/' | 
					
						
							| 
									
										
										
										
											2022-09-25 19:22:32 +03:00
										 |  |  | 		path = this.unquote( | 
					
						
							|  |  |  | 				path instanceof Array ? | 
					
						
							|  |  |  | 					path.join('/') | 
					
						
							|  |  |  | 					: path) | 
					
						
							| 
									
										
										
										
											2022-08-15 14:29:45 +03:00
										 |  |  | 			// NOTE: this will also trim the path elements...
 | 
					
						
							|  |  |  | 			.split(/\s*[\\\/]+\s*/) | 
					
						
							| 
									
										
										
										
											2022-08-03 01:35:19 +03:00
										 |  |  | 			.reduce(function(res, e, i, L){ | 
					
						
							|  |  |  | 				// special case: leading '..' / '.'
 | 
					
						
							|  |  |  | 				if(res.length == 0  | 
					
						
							|  |  |  | 						&& e == '..'){ | 
					
						
							|  |  |  | 					return [e] } | 
					
						
							| 
									
										
										
										
											2022-09-22 02:52:14 +03:00
										 |  |  | 				// multiple leading '..'...
 | 
					
						
							|  |  |  | 				;(e == '..'  | 
					
						
							|  |  |  | 						&& res.at(-1) == '..' ? | 
					
						
							|  |  |  | 					res.push(e) | 
					
						
							|  |  |  | 				: e == '.'  | 
					
						
							| 
									
										
										
										
											2022-08-03 01:35:19 +03:00
										 |  |  | 						// keep explicit '/' only at start/end of path...
 | 
					
						
							|  |  |  | 						|| (e == ''  | 
					
						
							|  |  |  | 							&& i != 0  | 
					
						
							|  |  |  | 							&& i != L.length-1)) ? | 
					
						
							|  |  |  | 					undefined | 
					
						
							|  |  |  | 				: e == '..'  | 
					
						
							| 
									
										
										
										
											2022-09-22 02:52:14 +03:00
										 |  |  | 						|| res.at(-1) == '>>' ? | 
					
						
							| 
									
										
										
										
											2022-08-03 01:35:19 +03:00
										 |  |  | 					((res.length > 1  | 
					
						
							|  |  |  | 							|| res[0] != '') | 
					
						
							|  |  |  | 						&& res.pop()) | 
					
						
							|  |  |  | 				// NOTE: the last '>>' will be retained...
 | 
					
						
							|  |  |  | 				: res.push(e) | 
					
						
							|  |  |  | 				return res }, [])  | 
					
						
							| 
									
										
										
										
											2022-09-03 10:57:18 +03:00
										 |  |  | 		// clear the trailing '/'...
 | 
					
						
							|  |  |  | 		path.at(-1) == '' | 
					
						
							|  |  |  | 			&& path.pop() | 
					
						
							| 
									
										
										
										
											2022-09-20 11:41:38 +03:00
										 |  |  | 		// trim trailing ':'...
 | 
					
						
							|  |  |  | 		path.at(-1)  | 
					
						
							|  |  |  | 			&& path.at(-1).endsWith(':') | 
					
						
							|  |  |  | 			&& (path.push( | 
					
						
							|  |  |  | 				path.pop() | 
					
						
							|  |  |  | 					.replace(/:*$/, ''))) | 
					
						
							| 
									
										
										
										
											2022-08-24 23:13:24 +03:00
										 |  |  | 		/*/ XXX NORMCACHE... | 
					
						
							|  |  |  | 		var res = format == 'string' ? | 
					
						
							|  |  |  | 			// special case: root -> keep '/'
 | 
					
						
							|  |  |  | 			((root  | 
					
						
							|  |  |  | 					&& path.length == 1  | 
					
						
							|  |  |  | 					&& path[0] == '') ? | 
					
						
							|  |  |  | 				('/'+ path.join('/')) | 
					
						
							|  |  |  | 				: path.join('/')) | 
					
						
							|  |  |  | 			: path  | 
					
						
							|  |  |  | 		typeof(res) == 'string' | 
					
						
							|  |  |  | 			&& this._normalized_cache.add(res) | 
					
						
							|  |  |  | 		return res }, | 
					
						
							|  |  |  | 		/*/ | 
					
						
							| 
									
										
										
										
											2022-08-03 01:35:19 +03:00
										 |  |  | 		return format == 'string' ? | 
					
						
							|  |  |  | 			// special case: root -> keep '/'
 | 
					
						
							|  |  |  | 			((root  | 
					
						
							|  |  |  | 					&& path.length == 1  | 
					
						
							|  |  |  | 					&& path[0] == '') ? | 
					
						
							|  |  |  | 				('/'+ path.join('/')) | 
					
						
							|  |  |  | 				: path.join('/')) | 
					
						
							|  |  |  | 			: path }, | 
					
						
							| 
									
										
										
										
											2022-08-24 23:13:24 +03:00
										 |  |  | 		//*/
 | 
					
						
							| 
									
										
										
										
											2022-09-04 11:06:19 +03:00
										 |  |  | 	sanitize: function(path, format='auto'){ | 
					
						
							|  |  |  | 		format = format == 'auto' ? | 
					
						
							|  |  |  | 			(path instanceof Array ? | 
					
						
							|  |  |  | 				'array' | 
					
						
							|  |  |  | 				: 'string') | 
					
						
							|  |  |  | 			: format | 
					
						
							|  |  |  | 		path = this.split(path) | 
					
						
							| 
									
										
										
										
											2022-09-22 02:52:14 +03:00
										 |  |  | 		// leading: '/', '.' and '..'...
 | 
					
						
							|  |  |  | 		while(path[0] == '' | 
					
						
							| 
									
										
										
										
											2022-09-04 11:06:19 +03:00
										 |  |  | 				|| path[0] == '.' | 
					
						
							| 
									
										
										
										
											2022-09-22 02:52:14 +03:00
										 |  |  | 				|| path[0] == '..'){ | 
					
						
							|  |  |  | 			path.shift() } | 
					
						
							|  |  |  | 		//trailing '/'
 | 
					
						
							| 
									
										
										
										
											2022-09-04 11:06:19 +03:00
										 |  |  | 		path.at(-1) == '' | 
					
						
							|  |  |  | 			&& path.pop() | 
					
						
							|  |  |  | 		return format == 'string' ? | 
					
						
							|  |  |  | 			path.join('/') | 
					
						
							|  |  |  | 			: path }, | 
					
						
							| 
									
										
										
										
											2022-08-03 01:35:19 +03:00
										 |  |  | 	split: function(path){ | 
					
						
							|  |  |  | 		return this.normalize(path, 'array') }, | 
					
						
							|  |  |  | 	join: function(...parts){ | 
					
						
							|  |  |  | 		return this.normalize( | 
					
						
							|  |  |  | 			(parts[0] instanceof Array ? | 
					
						
							|  |  |  | 					parts[0] | 
					
						
							| 
									
										
										
										
											2022-08-15 14:29:45 +03:00
										 |  |  | 					: parts),  | 
					
						
							| 
									
										
										
										
											2022-08-03 01:35:19 +03:00
										 |  |  | 			'string') }, | 
					
						
							|  |  |  | 	basename: function(path){ | 
					
						
							| 
									
										
										
										
											2022-08-10 15:29:45 +03:00
										 |  |  | 		path = this.split(path) | 
					
						
							| 
									
										
										
										
											2022-10-03 02:35:14 +03:00
										 |  |  | 		return path.length == 0 ? | 
					
						
							|  |  |  | 				'' | 
					
						
							|  |  |  | 			: path.length == 1 ? | 
					
						
							| 
									
										
										
										
											2022-08-10 15:29:45 +03:00
										 |  |  | 				path[0]	 | 
					
						
							|  |  |  | 			: (path.at(-1) == '' ? | 
					
						
							|  |  |  | 				path.at(-2) | 
					
						
							|  |  |  | 				: path.at(-1)) }, | 
					
						
							| 
									
										
										
										
											2022-08-03 01:35:19 +03:00
										 |  |  | 	dirname: function(path){ | 
					
						
							| 
									
										
										
										
											2022-08-10 15:29:45 +03:00
										 |  |  | 		path = this.split(path) | 
					
						
							|  |  |  | 		path = path.length == 1 ? | 
					
						
							| 
									
										
										
										
											2022-10-03 02:35:14 +03:00
										 |  |  | 				'/' | 
					
						
							| 
									
										
										
										
											2022-08-10 15:29:45 +03:00
										 |  |  | 			: path.length == 2 ? | 
					
						
							|  |  |  | 				path[0] | 
					
						
							|  |  |  | 			: (path.at(-1) == '' ? | 
					
						
							|  |  |  | 					path.slice(0, -2) | 
					
						
							|  |  |  | 					: path.slice(0, -1)) | 
					
						
							|  |  |  | 				.join('/')  | 
					
						
							|  |  |  | 		return path == '' ? | 
					
						
							|  |  |  | 			'/' | 
					
						
							|  |  |  | 			: path }, | 
					
						
							| 
									
										
										
										
											2022-08-03 01:35:19 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-08-10 15:29:45 +03:00
										 |  |  | 	// XXX BUG? which is more correct??
 | 
					
						
							|  |  |  | 	// 			.relative('a/b/c', 'x') 
 | 
					
						
							|  |  |  | 	// 				-> 'a/b/c/x' (current)
 | 
					
						
							|  |  |  | 	// 		or:
 | 
					
						
							|  |  |  | 	// 			.relative('a/b/c', 'x') 
 | 
					
						
							|  |  |  | 	// 				-> 'a/b/x' 
 | 
					
						
							|  |  |  | 	// 		...not sure about this yet...
 | 
					
						
							|  |  |  | 	// 		XXX REVISE...
 | 
					
						
							| 
									
										
										
										
											2022-08-03 01:35:19 +03:00
										 |  |  | 	relative: function(parent, path, format='auto'){ | 
					
						
							|  |  |  | 		format = format == 'auto' ? | 
					
						
							|  |  |  | 			(path instanceof Array ? | 
					
						
							|  |  |  | 				'array' | 
					
						
							|  |  |  | 				: 'string') | 
					
						
							|  |  |  | 			: format | 
					
						
							|  |  |  | 		// root path...
 | 
					
						
							|  |  |  | 		if(path[0] == '' || path[0] == '/'){ | 
					
						
							|  |  |  | 			return this.normalize(path, format) } | 
					
						
							|  |  |  | 		// unify parent/path types...
 | 
					
						
							|  |  |  | 		parent = parent instanceof Array ? | 
					
						
							|  |  |  | 			parent | 
					
						
							|  |  |  | 			: parent.split(/\s*[\\\/]+\s*/) | 
					
						
							|  |  |  | 		path = path instanceof Array ? | 
					
						
							|  |  |  | 			path | 
					
						
							|  |  |  | 			: path.split(/\s*[\\\/]+\s*/) | 
					
						
							| 
									
										
										
										
											2022-08-10 15:29:45 +03:00
										 |  |  | 		// NOTE: relative paths are siblings and not children unless the 
 | 
					
						
							|  |  |  | 		// 		parent is explicitly a directory (i.e. ends in '/')...
 | 
					
						
							|  |  |  | 		/* XXX RELATIVE -- leading @ in path is the same as a trailing / in parent... | 
					
						
							|  |  |  | 		path[0] == '@' ? | 
					
						
							|  |  |  | 			path.shift() | 
					
						
							|  |  |  | 			: parent.pop() | 
					
						
							|  |  |  | 		//*/
 | 
					
						
							| 
									
										
										
										
											2022-08-03 01:35:19 +03:00
										 |  |  | 		return this.normalize([...parent, ...path], format) }, | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// Build alternative paths for page acquisition...
 | 
					
						
							|  |  |  | 	//
 | 
					
						
							|  |  |  | 	// NOTE: if seen is given (when called recursively) this will not 
 | 
					
						
							|  |  |  | 	// 		search for .ALTERNATIVE_PAGES...
 | 
					
						
							| 
									
										
										
										
											2022-08-06 11:09:25 +03:00
										 |  |  | 	// NOTE: this will search for basename and each subpath, e.g:
 | 
					
						
							|  |  |  | 	// 			a/b/c	
 | 
					
						
							|  |  |  | 	// 				-> a/b/c/d
 | 
					
						
							|  |  |  | 	// 				-> a/c/d
 | 
					
						
							|  |  |  | 	// 				-> c/d
 | 
					
						
							|  |  |  | 	// 				-> d
 | 
					
						
							|  |  |  | 	// 				// now search for 'c/d'...
 | 
					
						
							|  |  |  | 	// 				-> a/c/d
 | 
					
						
							|  |  |  | 	// 				-> ...
 | 
					
						
							| 
									
										
										
										
											2022-08-03 01:35:19 +03:00
										 |  |  | 	// XXX should we keep the trailing '/'???
 | 
					
						
							| 
									
										
										
										
											2022-08-05 12:46:00 +03:00
										 |  |  | 	paths: function*(path='/', strict=false){ | 
					
						
							|  |  |  | 		if(path === true || path === false){ | 
					
						
							|  |  |  | 			strict = path | 
					
						
							|  |  |  | 			path = '/' } | 
					
						
							|  |  |  | 		var alt_pages = !strict | 
					
						
							|  |  |  | 		var seen = strict instanceof Set ? | 
					
						
							|  |  |  | 			strict | 
					
						
							|  |  |  | 			: new Set() | 
					
						
							| 
									
										
										
										
											2022-08-03 01:35:19 +03:00
										 |  |  | 		path = this.normalize(path, 'string') | 
					
						
							|  |  |  | 		// special case: root...
 | 
					
						
							|  |  |  | 		if(path == '/' || path == ''){ | 
					
						
							|  |  |  | 			// normalize...
 | 
					
						
							|  |  |  | 			path = '/' | 
					
						
							|  |  |  | 			// as-is...
 | 
					
						
							|  |  |  | 			seen.add(path) | 
					
						
							|  |  |  | 			yield path | 
					
						
							|  |  |  | 			// special case: root page...
 | 
					
						
							|  |  |  | 			if(this.ROOT_PAGE){ | 
					
						
							|  |  |  | 				yield* this.paths(this.normalize('/'+ this.ROOT_PAGE, 'string'), seen) }} | 
					
						
							|  |  |  | 		// NOTE: since path is already normalized we can trust the delimiter...
 | 
					
						
							|  |  |  | 		path = path.split(/\//g) | 
					
						
							|  |  |  | 		// normalize relative paths to root...
 | 
					
						
							|  |  |  | 		path[0] != '' | 
					
						
							|  |  |  | 			&& path.unshift('') | 
					
						
							|  |  |  | 		// paths ending in '/'...
 | 
					
						
							|  |  |  | 		if(path[path.length-1] == ''){ | 
					
						
							|  |  |  | 			path.pop() | 
					
						
							|  |  |  | 			this.INDEX_PAGE | 
					
						
							|  |  |  | 				&& path.push(this.INDEX_PAGE) } | 
					
						
							|  |  |  | 		// search for page...
 | 
					
						
							|  |  |  | 		var page = path.pop() | 
					
						
							| 
									
										
										
										
											2022-09-17 17:13:23 +03:00
										 |  |  | 		for(var tpl of ['.', ...this.SEARCH_PATHS, this.SYSTEM_PATH]){ | 
					
						
							| 
									
										
										
										
											2022-08-03 01:35:19 +03:00
										 |  |  | 			// search for page up the path...
 | 
					
						
							| 
									
										
										
										
											2022-08-06 11:09:25 +03:00
										 |  |  | 			var pg = page | 
					
						
							|  |  |  | 			var base = path.slice() | 
					
						
							|  |  |  | 			while(base.length > 0){ | 
					
						
							|  |  |  | 				var p = base.slice() | 
					
						
							|  |  |  | 				while(p.length > 0){ | 
					
						
							| 
									
										
										
										
											2022-08-10 15:29:45 +03:00
										 |  |  | 					// NOTE: we are adding '' to path here to get things 
 | 
					
						
							|  |  |  | 					// 		relative to it and not relative to basedir...
 | 
					
						
							|  |  |  | 					var cur = this.relative([...p, ''], tpl +'/'+ pg, 'string') | 
					
						
							| 
									
										
										
										
											2022-08-06 11:09:25 +03:00
										 |  |  | 					if(!seen.has(cur)){ | 
					
						
							|  |  |  | 						seen.add(cur) | 
					
						
							|  |  |  | 						yield cur } | 
					
						
							|  |  |  | 					// special case: non-relative template/page path...
 | 
					
						
							|  |  |  | 					if(tpl[0] == '/'){ | 
					
						
							|  |  |  | 						break } | 
					
						
							|  |  |  | 					p.pop() }  | 
					
						
							|  |  |  | 				// next search for tail sub-path...
 | 
					
						
							|  |  |  | 				// 		for a/b/c
 | 
					
						
							|  |  |  | 				// 			c in a/b -> b/c in a
 | 
					
						
							|  |  |  | 				pg = base.pop() +'/'+ pg } } | 
					
						
							| 
									
										
										
										
											2022-08-03 01:35:19 +03:00
										 |  |  | 		// alternative pages...
 | 
					
						
							|  |  |  | 		if(alt_pages){ | 
					
						
							|  |  |  | 			for(var page of [...this.ALTERNATIVE_PAGES]){ | 
					
						
							|  |  |  | 				yield* this.paths(path.concat(page), seen) }} }, | 
					
						
							| 
									
										
										
										
											2022-08-21 12:31:04 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-08-24 23:13:24 +03:00
										 |  |  | 	names: function(path='/'){ | 
					
						
							| 
									
										
										
										
											2022-10-03 02:35:14 +03:00
										 |  |  | 		path = path == '' ? | 
					
						
							|  |  |  | 			'/' | 
					
						
							|  |  |  | 			: path | 
					
						
							| 
									
										
										
										
											2022-08-24 23:13:24 +03:00
										 |  |  | 		path = this.normalize(path, 'string') | 
					
						
							|  |  |  | 		var name = path == '/' ? | 
					
						
							|  |  |  | 			this.ROOT_PAGE | 
					
						
							|  |  |  | 			: this.basename(path) | 
					
						
							|  |  |  | 		return name == '' ? | 
					
						
							|  |  |  | 			this.ALTERNATIVE_PAGES.slice() | 
					
						
							|  |  |  | 			: [name, ...this.ALTERNATIVE_PAGES] }, | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-08-21 12:31:04 +03:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	//
 | 
					
						
							| 
									
										
										
										
											2022-08-31 15:46:51 +03:00
										 |  |  | 	//	.splitArgs(<path>)
 | 
					
						
							| 
									
										
										
										
											2022-08-21 12:31:04 +03:00
										 |  |  | 	//		-> <spec>
 | 
					
						
							|  |  |  | 	//
 | 
					
						
							|  |  |  | 	// Format:
 | 
					
						
							|  |  |  | 	// 	{
 | 
					
						
							|  |  |  | 	// 		path: <path>
 | 
					
						
							|  |  |  | 	// 		args: {
 | 
					
						
							|  |  |  | 	// 			<name>:<value>,
 | 
					
						
							|  |  |  | 	// 			...
 | 
					
						
							|  |  |  | 	// 		}
 | 
					
						
							|  |  |  | 	// 	}
 | 
					
						
							|  |  |  | 	//
 | 
					
						
							|  |  |  | 	// Syntax:
 | 
					
						
							| 
									
										
										
										
											2022-08-21 18:10:39 +03:00
										 |  |  | 	// 		<path> ::= <path>:<args>
 | 
					
						
							|  |  |  | 	// 		<args> ::=
 | 
					
						
							|  |  |  | 	// 			<arg> | <arg>:<args>
 | 
					
						
							|  |  |  | 	// 		<arg> ::=
 | 
					
						
							|  |  |  | 	// 			<value>
 | 
					
						
							| 
									
										
										
										
											2022-08-22 19:23:06 +03:00
										 |  |  | 	// 			| <name>=<value>
 | 
					
						
							| 
									
										
										
										
											2022-08-21 12:31:04 +03:00
										 |  |  | 	//
 | 
					
						
							|  |  |  | 	// XXX the problem here is that we could legitimately create path 
 | 
					
						
							|  |  |  | 	// 		items containing ":" -- it either needs to be a reserved char
 | 
					
						
							|  |  |  | 	// 		or this scheme will not work...
 | 
					
						
							|  |  |  | 	splitArgs: function(path){ | 
					
						
							| 
									
										
										
										
											2022-08-22 19:23:06 +03:00
										 |  |  | 		path = this.normalize(path, 'string') | 
					
						
							| 
									
										
										
										
											2022-08-31 15:46:51 +03:00
										 |  |  | 		var [path, ...args] = path.split(/(?<!\\):/g) | 
					
						
							| 
									
										
										
										
											2022-08-22 19:23:06 +03:00
										 |  |  | 		return { | 
					
						
							|  |  |  | 			path, | 
					
						
							|  |  |  | 			args: args.reduce(function(res, arg){ | 
					
						
							| 
									
										
										
										
											2022-08-31 15:46:51 +03:00
										 |  |  | 				var [name, value] = arg.split(/=(.*)/) | 
					
						
							| 
									
										
										
										
											2022-09-01 00:04:13 +03:00
										 |  |  | 				res[name.trim()] = value ?? true | 
					
						
							| 
									
										
										
										
											2022-08-22 19:23:06 +03:00
										 |  |  | 				return res }, {}), | 
					
						
							|  |  |  | 		} }, | 
					
						
							| 
									
										
										
										
											2022-08-31 15:46:51 +03:00
										 |  |  | 	obj2args: function(args){ | 
					
						
							|  |  |  | 		return args instanceof Object ? | 
					
						
							|  |  |  | 			Object.entries(args) | 
					
						
							|  |  |  | 				.map(function([key, value]){ | 
					
						
							|  |  |  | 					return value === true ? | 
					
						
							|  |  |  | 							key | 
					
						
							| 
									
										
										
										
											2022-09-01 00:04:13 +03:00
										 |  |  | 						: key +'='+ ((value + '').replace(/:/g, '\\:')) }) | 
					
						
							| 
									
										
										
										
											2022-08-31 15:46:51 +03:00
										 |  |  | 				.join(':')  | 
					
						
							|  |  |  | 			: args }, | 
					
						
							| 
									
										
										
										
											2022-09-01 00:04:13 +03:00
										 |  |  | 	joinArgs: function(path, args={}){ | 
					
						
							|  |  |  | 		path = this.join(path) | 
					
						
							|  |  |  | 		args = this.obj2args(args) | 
					
						
							|  |  |  | 		return args == '' ? | 
					
						
							|  |  |  | 			path | 
					
						
							|  |  |  | 			: path +':'+ args }, | 
					
						
							| 
									
										
										
										
											2022-08-03 01:35:19 +03:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /********************************************************************** | 
					
						
							|  |  |  | * vim:set ts=4 sw=4 :                               */ return module }) |