| 
									
										
										
										
											2016-07-04 19:51:37 +03:00
										 |  |  | /********************************************************************** | 
					
						
							|  |  |  | *  | 
					
						
							|  |  |  | * | 
					
						
							|  |  |  | * | 
					
						
							|  |  |  | **********************************************************************/ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-07-19 03:10:16 +03:00
										 |  |  | /*********************************************************************/ | 
					
						
							|  |  |  | // Hepers...
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | var path2lst = function(path){  | 
					
						
							|  |  |  | 	return (path instanceof Array ?  path : path.split(/[\\\/]+/g)) | 
					
						
							|  |  |  | 		// handle '..' (lookahead) and trim path elements...
 | 
					
						
							|  |  |  | 		// NOTE: this will not touch the leading '.' or '..'
 | 
					
						
							|  |  |  | 		.map(function(p, i, l){ | 
					
						
							|  |  |  | 			return (i > 0 && (p.trim() == '..' || p.trim() == '.') | 
					
						
							|  |  |  | 					|| (l[i+1] || '').trim() == '..') ?  | 
					
						
							|  |  |  | 				null  | 
					
						
							|  |  |  | 				: p.trim() }) | 
					
						
							|  |  |  | 		// cleanup and clear '.'...
 | 
					
						
							|  |  |  | 		.filter(function(p){  | 
					
						
							|  |  |  | 			return p != null && p != '' })} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | var normalizePath = function(path){ | 
					
						
							|  |  |  | 	return path2lst(path).join('/') } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | var clearWikiWords = function(elem){ | 
					
						
							| 
									
										
										
										
											2016-07-17 15:58:50 +03:00
										 |  |  | 	// clear existing...
 | 
					
						
							| 
									
										
										
										
											2016-07-19 23:13:51 +03:00
										 |  |  | 	elem.find('.wikiword').each(function(){ | 
					
						
							| 
									
										
										
										
											2016-07-20 02:32:17 +03:00
										 |  |  | 		$(this).attr('bracketed') == 'yes' ?  | 
					
						
							| 
									
										
										
										
											2016-07-17 15:58:50 +03:00
										 |  |  | 			$(this).replaceWith(['['].concat(this.childNodes, [']'])) | 
					
						
							|  |  |  | 			: $(this).replaceWith(this.childNodes) | 
					
						
							|  |  |  | 	}) | 
					
						
							| 
									
										
										
										
											2016-07-19 03:10:16 +03:00
										 |  |  | 	return elem }  | 
					
						
							| 
									
										
										
										
											2016-07-17 15:58:50 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-07-20 02:32:17 +03:00
										 |  |  | var setWikiWords = function(text, show_brackets, skip){ | 
					
						
							|  |  |  | 	skip = skip || [] | 
					
						
							|  |  |  | 	skip = skip instanceof Array ? skip : [skip] | 
					
						
							|  |  |  | 	return text  | 
					
						
							| 
									
										
										
										
											2016-07-17 15:58:50 +03:00
										 |  |  | 		// set new...
 | 
					
						
							|  |  |  | 		.replace( | 
					
						
							|  |  |  | 			Wiki.__wiki_link__, | 
					
						
							|  |  |  | 			function(l){ | 
					
						
							| 
									
										
										
										
											2016-07-22 21:46:23 +03:00
										 |  |  | 				var path = l[0] == '[' ? l.slice(1, -1) : l | 
					
						
							|  |  |  | 				var i = [].slice.call(arguments).slice(-2)[0] | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 				// XXX HACK check if we are inside a tag...
 | 
					
						
							|  |  |  | 				var rest = text.slice(i+1) | 
					
						
							|  |  |  | 				if(rest.indexOf('>') < rest.indexOf('<')){ | 
					
						
							|  |  |  | 					return l | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-07-20 02:32:17 +03:00
										 |  |  | 				return skip.indexOf(l) < 0 ?  | 
					
						
							|  |  |  | 					('<a ' | 
					
						
							|  |  |  | 						+'class="wikiword" ' | 
					
						
							| 
									
										
										
										
											2016-07-22 21:46:23 +03:00
										 |  |  | 						+'href="#'+ path +'" ' | 
					
						
							| 
									
										
										
										
											2016-07-20 02:32:17 +03:00
										 |  |  | 						+'bracketed="'+ (show_brackets && l[0] == '[' ? 'yes' : 'no') +'" ' | 
					
						
							| 
									
										
										
										
											2016-07-22 23:42:34 +03:00
										 |  |  | 						//+'onclick="event.preventDefault(); go($(this).attr(\'href\').slice(1))" '
 | 
					
						
							| 
									
										
										
										
											2016-07-20 02:32:17 +03:00
										 |  |  | 						+'>' | 
					
						
							| 
									
										
										
										
											2016-07-22 21:46:23 +03:00
										 |  |  | 							+ (!!show_brackets ? path : l)  | 
					
						
							| 
									
										
										
										
											2016-07-20 02:32:17 +03:00
										 |  |  | 						+'</a>') | 
					
						
							|  |  |  | 					: l | 
					
						
							| 
									
										
										
										
											2016-07-19 03:10:16 +03:00
										 |  |  | 			})} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /*********************************************************************/ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-07-21 17:03:43 +03:00
										 |  |  | function Macro(doc, args, func){ | 
					
						
							|  |  |  | 	func.doc = doc | 
					
						
							|  |  |  | 	func.macro_args = args | 
					
						
							|  |  |  | 	return func  | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-07-27 00:08:11 +03:00
										 |  |  | 
 | 
					
						
							|  |  |  | // XXX should inline macros support named args???
 | 
					
						
							| 
									
										
										
										
											2016-07-27 00:10:14 +03:00
										 |  |  | var macro = { | 
					
						
							| 
									
										
										
										
											2016-07-27 00:08:11 +03:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	__include_marker__: '__include_marker__', | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// Abstract macro syntax:
 | 
					
						
							|  |  |  | 	// 	Inline macro:
 | 
					
						
							|  |  |  | 	// 		@macro(arg ..)
 | 
					
						
							|  |  |  | 	//
 | 
					
						
							|  |  |  | 	// 	HTML-like:
 | 
					
						
							|  |  |  | 	// 		<macro arg=value ../>
 | 
					
						
							|  |  |  | 	//
 | 
					
						
							|  |  |  | 	// 	HTML-like with body:
 | 
					
						
							|  |  |  | 	// 		<macro arg=value ..>
 | 
					
						
							|  |  |  | 	// 			..text..
 | 
					
						
							|  |  |  | 	// 		</macro>
 | 
					
						
							|  |  |  | 	//
 | 
					
						
							|  |  |  | 	// XXX should inline macros support named args???
 | 
					
						
							|  |  |  | 	__macro__pattern__:  | 
					
						
							|  |  |  | 		[[ | 
					
						
							|  |  |  | 			// @macro(arg ..)
 | 
					
						
							|  |  |  | 			'@([a-zA-Z-_]+)\\(([^)]*)\\)' | 
					
						
							|  |  |  | 		].join('|'), 'mg'], | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// default filters...
 | 
					
						
							|  |  |  | 	//
 | 
					
						
							|  |  |  | 	// NOTE: these are added AFTER the user defined filters...
 | 
					
						
							|  |  |  | 	__filters__: [ | 
					
						
							|  |  |  | 		'wikiword', | 
					
						
							|  |  |  | 	], | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// Macros...
 | 
					
						
							|  |  |  | 	//
 | 
					
						
							|  |  |  | 	macro: { | 
					
						
							|  |  |  | 		// select filter to post-process text...
 | 
					
						
							|  |  |  | 		filter: Macro('Filter to post-process text', | 
					
						
							|  |  |  | 			['name'], | 
					
						
							|  |  |  | 			function(context, elem, state){ | 
					
						
							|  |  |  | 				var filter = $(elem).attr('name') | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 				filter[0] == '-' ? | 
					
						
							|  |  |  | 					// disabled -- keep at head of list...
 | 
					
						
							|  |  |  | 					state.filters.unshift(filter) | 
					
						
							|  |  |  | 					// normal -- tail...
 | 
					
						
							|  |  |  | 					: state.filters.push(filter) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 				return '' | 
					
						
							|  |  |  | 			}), | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		// include page/slot...
 | 
					
						
							|  |  |  | 		//
 | 
					
						
							|  |  |  | 		// NOTE: this will render the page in the caller's context.
 | 
					
						
							|  |  |  | 		// NOTE: included pages are rendered completely independently 
 | 
					
						
							|  |  |  | 		// 		from the including page.
 | 
					
						
							|  |  |  | 		//
 | 
					
						
							|  |  |  | 		// XXX do we need to control the rendering of nested pages???
 | 
					
						
							|  |  |  | 		// 		...currently I do not think so...
 | 
					
						
							|  |  |  | 		// 		...if required this can be done via global and local 
 | 
					
						
							|  |  |  | 		// 		filters... (now filters are only local)
 | 
					
						
							|  |  |  | 		// XXX do we need to render just one slot??? (slot arg)
 | 
					
						
							|  |  |  | 		// 		e.g. include PageX SlotY
 | 
					
						
							|  |  |  | 		include: Macro('Include page', | 
					
						
							|  |  |  | 			['src'], | 
					
						
							|  |  |  | 			function(context, elem, state){ | 
					
						
							|  |  |  | 				var path = $(elem).attr('src') | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 				// get and prepare the included page...
 | 
					
						
							|  |  |  | 				state.include | 
					
						
							| 
									
										
										
										
											2016-07-28 09:07:46 +03:00
										 |  |  | 					.push([elem, context.get(path)]) | 
					
						
							| 
									
										
										
										
											2016-07-27 00:08:11 +03:00
										 |  |  | 
 | 
					
						
							|  |  |  | 				// return the marker...
 | 
					
						
							|  |  |  | 				return this.__include_marker__ | 
					
						
							|  |  |  | 			}), | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		// NOTE: this is similar to include, the difference is that this
 | 
					
						
							|  |  |  | 		// 		includes the page source to the current context while 
 | 
					
						
							|  |  |  | 		// 		include works in an isolated context
 | 
					
						
							|  |  |  | 		source: Macro('Include page source (without parsing)', | 
					
						
							|  |  |  | 			['src'],  | 
					
						
							|  |  |  | 			function(context, elem, state){ | 
					
						
							|  |  |  | 				var path = $(elem).attr('src') | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 				return context.get(path).raw | 
					
						
							|  |  |  | 			}), | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-07-28 09:07:46 +03:00
										 |  |  | 		quote: Macro('Include quoted page source (without parsing)', | 
					
						
							|  |  |  | 			['src'],  | 
					
						
							|  |  |  | 			function(context, elem, state){ | 
					
						
							|  |  |  | 				elem = $(elem) | 
					
						
							|  |  |  | 				var path = elem.attr('src') | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 				return elem.text(context.get(path).raw) | 
					
						
							|  |  |  | 			}), | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		/* | 
					
						
							| 
									
										
										
										
											2016-07-27 00:08:11 +03:00
										 |  |  | 		// fill/define slot (stage 1)...
 | 
					
						
							|  |  |  | 		//
 | 
					
						
							|  |  |  | 		// XXX which should have priority the arg text or the content???
 | 
					
						
							| 
									
										
										
										
											2016-07-28 09:07:46 +03:00
										 |  |  | 		_slot: Macro('Define/fill slot', | 
					
						
							| 
									
										
										
										
											2016-07-27 00:08:11 +03:00
										 |  |  | 			['name', 'text'], | 
					
						
							| 
									
										
										
										
											2016-07-28 09:07:46 +03:00
										 |  |  | 			function(context, elem, state, parse){ | 
					
						
							| 
									
										
										
										
											2016-07-27 00:08:11 +03:00
										 |  |  | 				var name = $(elem).attr('name') | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 				// XXX
 | 
					
						
							|  |  |  | 				text = $(elem).html() | 
					
						
							|  |  |  | 				text = text == '' ? $(elem).attr('text') : text | 
					
						
							|  |  |  | 				text = this.parse(context, text, state, true) | 
					
						
							| 
									
										
										
										
											2016-07-28 09:07:46 +03:00
										 |  |  | 				//text = parse(elem)
 | 
					
						
							| 
									
										
										
										
											2016-07-27 00:08:11 +03:00
										 |  |  | 
 | 
					
						
							|  |  |  | 				if(state.slots[name] == null){ | 
					
						
							|  |  |  | 					state.slots[name] = text | 
					
						
							|  |  |  | 					// return a slot macro parsable by stage 2...
 | 
					
						
							| 
									
										
										
										
											2016-07-28 09:07:46 +03:00
										 |  |  | 					//return '<_slot name="'+name+'">'+ text +'</slot>'
 | 
					
						
							|  |  |  | 					return elem | 
					
						
							| 
									
										
										
										
											2016-07-27 00:08:11 +03:00
										 |  |  | 
 | 
					
						
							|  |  |  | 				} else if(name in state.slots){ | 
					
						
							|  |  |  | 					state.slots[name] = text | 
					
						
							|  |  |  | 					return '' | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 			}), | 
					
						
							| 
									
										
										
										
											2016-07-28 09:07:46 +03:00
										 |  |  | 		//*/
 | 
					
						
							|  |  |  | 		// convert @ macro to html-like + parse content...
 | 
					
						
							|  |  |  | 		slot: Macro('Define/fill slot', | 
					
						
							|  |  |  | 			['name', 'text'], | 
					
						
							|  |  |  | 			function(context, elem, state, parse){ | 
					
						
							|  |  |  | 				elem = $(elem) | 
					
						
							|  |  |  | 				var name = elem.attr('name') | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 				// XXX
 | 
					
						
							|  |  |  | 				text = elem.html() | 
					
						
							|  |  |  | 				text = text.trim() == '' ?  | 
					
						
							|  |  |  | 					elem.html(elem.attr('text') || '').html()  | 
					
						
							|  |  |  | 					: text | 
					
						
							|  |  |  | 				text = parse(elem) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 				elem.attr('text', null) | 
					
						
							|  |  |  | 				elem.html(text) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 				return elem | 
					
						
							|  |  |  | 			}), | 
					
						
							| 
									
										
										
										
											2016-07-27 00:08:11 +03:00
										 |  |  | 	}, | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	// Post macros... 
 | 
					
						
							|  |  |  | 	//
 | 
					
						
							|  |  |  | 	post_macro: { | 
					
						
							| 
									
										
										
										
											2016-07-28 09:07:46 +03:00
										 |  |  | 		/* | 
					
						
							|  |  |  | 		_slot: Macro('', | 
					
						
							| 
									
										
										
										
											2016-07-27 00:08:11 +03:00
										 |  |  | 			['name'], | 
					
						
							|  |  |  | 			function(context, elem, state){ | 
					
						
							|  |  |  | 				var name = $(elem).attr('name') | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 				if(state.slots[name] == null){ | 
					
						
							|  |  |  | 					return $(elem).html() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 				} else if(name in state.slots){ | 
					
						
							|  |  |  | 					return state.slots[name] | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 			}), | 
					
						
							| 
									
										
										
										
											2016-07-28 09:07:46 +03:00
										 |  |  | 		//*/
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		/* | 
					
						
							|  |  |  | 		// XXX rename to post-include and post-quote
 | 
					
						
							|  |  |  | 		'page-text': Macro('', | 
					
						
							|  |  |  | 			['src'], | 
					
						
							|  |  |  | 			function(context, elem, state){ | 
					
						
							|  |  |  | 				elem = $(elem) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 				return elem.html(context.get(elem.attr('src')).text) | 
					
						
							|  |  |  | 			}), | 
					
						
							|  |  |  | 		'page-raw': Macro('', | 
					
						
							|  |  |  | 			['src'], | 
					
						
							|  |  |  | 			function(context, elem, state){ | 
					
						
							|  |  |  | 				elem = $(elem) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 				return elem.text(context.get(elem.attr('src')).text) | 
					
						
							|  |  |  | 			}), | 
					
						
							|  |  |  | 		//*/
 | 
					
						
							| 
									
										
										
										
											2016-07-27 00:08:11 +03:00
										 |  |  | 	}, | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// Filters...
 | 
					
						
							|  |  |  | 	//
 | 
					
						
							|  |  |  | 	// Signature:
 | 
					
						
							|  |  |  | 	// 	filter(text) -> html
 | 
					
						
							|  |  |  | 	//
 | 
					
						
							|  |  |  | 	filter: { | 
					
						
							|  |  |  | 		default: 'html', | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		html: function(context, elem){ return $(elem) }, | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-07-27 02:13:15 +03:00
										 |  |  | 		text: function(context, elem){ return $('<span>') | 
					
						
							|  |  |  | 			.append($('<pre>') | 
					
						
							|  |  |  | 				.html($(elem).html())) }, | 
					
						
							|  |  |  | 		// XXX expperimental...
 | 
					
						
							|  |  |  | 		json: function(context, elem){ return $('<span>') | 
					
						
							|  |  |  | 			.html($(elem).text() | 
					
						
							|  |  |  | 				// remove JS comments...
 | 
					
						
							|  |  |  | 				.replace(/\s*\/\/.*$|\s*\/\*(.|[\n\r])*?\*\/\s*/mg, '')) }, | 
					
						
							| 
									
										
										
										
											2016-07-27 00:08:11 +03:00
										 |  |  | 
 | 
					
						
							|  |  |  | 		// XXX
 | 
					
						
							| 
									
										
										
										
											2016-07-27 02:38:17 +03:00
										 |  |  | 		nl2br: function(context, elem){  | 
					
						
							|  |  |  | 			return $('<div>').html($(elem).html().replace(/\n/g, '<br>\n')) }, | 
					
						
							| 
									
										
										
										
											2016-07-27 00:08:11 +03:00
										 |  |  | 
 | 
					
						
							|  |  |  | 		wikiword: function(context, elem){  | 
					
						
							|  |  |  | 			return $('<span>') | 
					
						
							|  |  |  | 				.html(setWikiWords($(elem).html(), true, this.__include_marker__)) }, | 
					
						
							| 
									
										
										
										
											2016-07-27 16:59:17 +03:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		// XXX move this to a plugin...
 | 
					
						
							|  |  |  | 		markdown: function(context, elem){ | 
					
						
							|  |  |  | 			var converter = new showdown.Converter() | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-07-27 17:04:38 +03:00
										 |  |  | 			return $('<span>') | 
					
						
							|  |  |  | 				.html(converter.makeHtml($(elem).html())) | 
					
						
							| 
									
										
										
										
											2016-07-27 16:59:17 +03:00
										 |  |  | 		}, | 
					
						
							| 
									
										
										
										
											2016-07-27 00:08:11 +03:00
										 |  |  | 	}, | 
					
						
							| 
									
										
										
										
											2016-07-25 22:08:44 +03:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-07-27 00:10:14 +03:00
										 |  |  | 	// Parsing:
 | 
					
						
							|  |  |  | 	//  1) expand macros
 | 
					
						
							|  |  |  | 	//  2) apply filters
 | 
					
						
							|  |  |  | 	//  3) merge and parse included pages:
 | 
					
						
							|  |  |  | 	//  	1) expand macros
 | 
					
						
							|  |  |  | 	//  	2) apply filters
 | 
					
						
							| 
									
										
										
										
											2016-07-28 09:07:46 +03:00
										 |  |  | 	//  4) fill slots
 | 
					
						
							|  |  |  | 	//  5) expand post-macros
 | 
					
						
							| 
									
										
										
										
											2016-07-27 00:10:14 +03:00
										 |  |  | 	//
 | 
					
						
							|  |  |  | 	// NOTE: stage 4 parsing is executed on the final merged page only 
 | 
					
						
							|  |  |  | 	// 		once. i.e. it is not performed on the included pages.
 | 
					
						
							|  |  |  | 	// NOTE: included pages are parsed in their own context.
 | 
					
						
							|  |  |  | 	// NOTE: slots are parsed in the context of their containing page 
 | 
					
						
							|  |  |  | 	// 		and not in the location they are being placed.
 | 
					
						
							|  |  |  | 	//
 | 
					
						
							|  |  |  | 	// XXX support quoted text...
 | 
					
						
							| 
									
										
										
										
											2016-07-27 02:13:15 +03:00
										 |  |  | 	// XXX need to quote regexp chars of .__include_marker__...
 | 
					
						
							| 
									
										
										
										
											2016-07-27 00:08:11 +03:00
										 |  |  | 	parse: function(context, text, state, skip_post, pattern){ | 
					
						
							| 
									
										
										
										
											2016-07-25 22:08:44 +03:00
										 |  |  | 		var that = this | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		state = state || {} | 
					
						
							|  |  |  | 		state.filters = state.filters || [] | 
					
						
							|  |  |  | 		state.slots = state.slots || {} | 
					
						
							|  |  |  | 		state.include = state.include || [] | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-07-27 00:08:11 +03:00
										 |  |  | 		//pattern = pattern || RegExp('@([a-zA-Z-_]+)\\(([^)]*)\\)', 'mg')
 | 
					
						
							|  |  |  | 		pattern = pattern || RegExp.apply(null, this.__macro__pattern__) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		// XXX need to quote regexp chars...
 | 
					
						
							|  |  |  | 		var include_marker = RegExp(this.__include_marker__, 'g') | 
					
						
							| 
									
										
										
										
											2016-07-26 07:53:44 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-07-27 00:08:11 +03:00
										 |  |  | 		var parsed = typeof(text) == typeof('str') ?  | 
					
						
							|  |  |  | 			$('<span>').html(text)  | 
					
						
							|  |  |  | 			: text | 
					
						
							| 
									
										
										
										
											2016-07-26 07:53:44 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-07-25 22:08:44 +03:00
										 |  |  | 		var _parseText = function(context, text, macro){ | 
					
						
							|  |  |  | 			return text.replace(pattern, function(match){ | 
					
						
							|  |  |  | 				// XXX parse match...
 | 
					
						
							| 
									
										
										
										
											2016-07-27 02:13:15 +03:00
										 |  |  | 				var d = match.match(/@([a-zA-Z-_:]*)\(([^)]*)\)/) | 
					
						
							| 
									
										
										
										
											2016-07-26 07:07:51 +03:00
										 |  |  | 
 | 
					
						
							|  |  |  | 				var name = d[1] | 
					
						
							| 
									
										
										
										
											2016-07-25 22:08:44 +03:00
										 |  |  | 
 | 
					
						
							|  |  |  | 				if(name in macro){ | 
					
						
							| 
									
										
										
										
											2016-07-26 07:07:51 +03:00
										 |  |  | 					var elem = $('<'+name+'/>') | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 					// format positional args....
 | 
					
						
							|  |  |  | 					var a = d[2] | 
					
						
							|  |  |  | 						.split(/((['"]).*?\2)|\s+/g) | 
					
						
							|  |  |  | 						// cleanup...
 | 
					
						
							|  |  |  | 						.filter(function(e){ return e && e != '' && !/^['"]$/.test(e)}) | 
					
						
							|  |  |  | 						// remove quotes...
 | 
					
						
							|  |  |  | 						.map(function(e){ return /^(['"]).*\1$/.test(e) ? e.slice(1, -1) : e }) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 					// add the attrs to the element...
 | 
					
						
							|  |  |  | 					a.forEach(function(e, i){ | 
					
						
							| 
									
										
										
										
											2016-07-26 07:53:44 +03:00
										 |  |  | 						var k = ((macro[name] || {}).macro_args || [])[i] | 
					
						
							| 
									
										
										
										
											2016-07-26 07:07:51 +03:00
										 |  |  | 						k && elem.attr(k, e) | 
					
						
							|  |  |  | 					}) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 					// call macro...
 | 
					
						
							| 
									
										
										
										
											2016-07-28 09:07:46 +03:00
										 |  |  | 					var res = macro[name] | 
					
						
							|  |  |  | 						.call(that, context, elem, state, | 
					
						
							|  |  |  | 							function(elem){ _parse(context, elem, macro) }) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 					return res instanceof $ ? res[0].outerHTML  | 
					
						
							|  |  |  | 						: typeof(res) != typeof('str') ? res.outerHTML | 
					
						
							|  |  |  | 						: res | 
					
						
							| 
									
										
										
										
											2016-07-25 22:08:44 +03:00
										 |  |  | 				} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 				return match | 
					
						
							|  |  |  | 			}) | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2016-07-26 07:53:44 +03:00
										 |  |  | 		// NOTE: this modifies parsed in-place...
 | 
					
						
							| 
									
										
										
										
											2016-07-25 22:08:44 +03:00
										 |  |  | 		var _parse = function(context, parsed, macro){ | 
					
						
							| 
									
										
										
										
											2016-07-26 07:53:44 +03:00
										 |  |  | 			$(parsed).contents().each(function(_, e){ | 
					
						
							| 
									
										
										
										
											2016-07-27 01:07:41 +03:00
										 |  |  | 				// #text / comment node -> parse the @... macros...
 | 
					
						
							|  |  |  | 				if(e.nodeType == e.TEXT_NODE || e.nodeType == e.COMMENT_NODE){ | 
					
						
							|  |  |  | 					// get actual element content...
 | 
					
						
							|  |  |  | 					var text = $('<div>').append($(e).clone()).html() | 
					
						
							| 
									
										
										
										
											2016-07-26 07:07:51 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-07-27 01:07:41 +03:00
										 |  |  | 					$(e).replaceWith(_parseText(context, text, macro)) | 
					
						
							| 
									
										
										
										
											2016-07-25 22:08:44 +03:00
										 |  |  | 
 | 
					
						
							|  |  |  | 				// node -> html-style + attrs...
 | 
					
						
							|  |  |  | 				} else { | 
					
						
							|  |  |  | 					var name = e.nodeName.toLowerCase() | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-07-26 07:07:51 +03:00
										 |  |  | 					// macro match -> call macro...
 | 
					
						
							| 
									
										
										
										
											2016-07-25 22:08:44 +03:00
										 |  |  | 					if(name in  macro){ | 
					
						
							| 
									
										
										
										
											2016-07-28 09:07:46 +03:00
										 |  |  | 						$(e).replaceWith(macro[name] | 
					
						
							|  |  |  | 							.call(that, context, e, state,  | 
					
						
							|  |  |  | 								function(elem){ _parse(context, elem, macro) })) | 
					
						
							| 
									
										
										
										
											2016-07-25 22:08:44 +03:00
										 |  |  | 
 | 
					
						
							|  |  |  | 					// normal tag -> attrs + sub-tree...
 | 
					
						
							|  |  |  | 					} else { | 
					
						
							|  |  |  | 						// parse attr values...
 | 
					
						
							|  |  |  | 						for(var i=0; i < e.attributes.length; i++){ | 
					
						
							|  |  |  | 							var attr = e.attributes[i] | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-07-26 07:53:44 +03:00
										 |  |  | 							attr.value = _parseText(context, attr.value, macro) | 
					
						
							| 
									
										
										
										
											2016-07-25 22:08:44 +03:00
										 |  |  | 						} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 						// parse sub-tree...
 | 
					
						
							|  |  |  | 						_parse(context, e, macro) | 
					
						
							|  |  |  | 					} | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 			}) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			return parsed | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-07-26 07:07:51 +03:00
										 |  |  | 		// macro stage...
 | 
					
						
							|  |  |  | 		_parse(context, parsed, this.macro) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		// filter stage...
 | 
					
						
							|  |  |  | 		state.filters | 
					
						
							|  |  |  | 			.concat(this.__filters__) | 
					
						
							|  |  |  | 			// unique -- leave last occurance..
 | 
					
						
							|  |  |  | 			.filter(function(k, i, lst){  | 
					
						
							|  |  |  | 				return k[0] != '-' | 
					
						
							|  |  |  | 					// filter dupplicates... 
 | 
					
						
							|  |  |  | 					&& lst.slice(i+1).indexOf(k) == -1  | 
					
						
							|  |  |  | 						// filter disabled...
 | 
					
						
							|  |  |  | 					&& lst.slice(0, i).indexOf('-' + k) == -1 | 
					
						
							|  |  |  | 			}) | 
					
						
							|  |  |  | 			// unique -- leave first occurance..
 | 
					
						
							|  |  |  | 			//.filter(function(k, i, lst){ return lst.slice(0, i).indexOf(k) == -1 })
 | 
					
						
							|  |  |  | 			// apply the filters...
 | 
					
						
							|  |  |  | 			.forEach(function(f){ | 
					
						
							|  |  |  | 				var k = f | 
					
						
							|  |  |  | 				// get filter aliases...
 | 
					
						
							|  |  |  | 				var seen = [] | 
					
						
							|  |  |  | 				while(typeof(k) == typeof('str') && seen.indexOf(k) == -1){ | 
					
						
							|  |  |  | 					seen.push(k) | 
					
						
							|  |  |  | 					k = that.filter[k] | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 				// could not find the filter...
 | 
					
						
							|  |  |  | 				if(!k){ | 
					
						
							| 
									
										
										
										
											2016-07-26 07:53:44 +03:00
										 |  |  | 					//console.warn('Unknown filter:', f)
 | 
					
						
							| 
									
										
										
										
											2016-07-26 07:07:51 +03:00
										 |  |  | 					return | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 				// use the filter...
 | 
					
						
							|  |  |  | 				parsed = k.call(that, context, parsed)  | 
					
						
							|  |  |  | 			}) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		// merge includes...
 | 
					
						
							| 
									
										
										
										
											2016-07-26 07:53:44 +03:00
										 |  |  | 		parsed | 
					
						
							| 
									
										
										
										
											2016-07-27 00:08:11 +03:00
										 |  |  | 			.html(parsed.html().replace(include_marker, function(){ | 
					
						
							| 
									
										
										
										
											2016-07-26 07:53:44 +03:00
										 |  |  | 				var page = state.include.shift() | 
					
						
							| 
									
										
										
										
											2016-07-28 09:07:46 +03:00
										 |  |  | 				var elem = $(page.shift()) | 
					
						
							|  |  |  | 				page = page.pop() | 
					
						
							| 
									
										
										
										
											2016-07-26 07:53:44 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-07-27 00:08:11 +03:00
										 |  |  | 				return $('<div>') | 
					
						
							| 
									
										
										
										
											2016-07-28 09:07:46 +03:00
										 |  |  | 					.append(elem//$('<include/>')
 | 
					
						
							| 
									
										
										
										
											2016-07-26 07:53:44 +03:00
										 |  |  | 						.attr('src', page.path) | 
					
						
							| 
									
										
										
										
											2016-07-27 00:08:11 +03:00
										 |  |  | 						//.append(page
 | 
					
						
							|  |  |  | 						//	.parse({ slots: state.slots }, true))
 | 
					
						
							|  |  |  | 						.append(that | 
					
						
							| 
									
										
										
										
											2016-07-27 01:07:41 +03:00
										 |  |  | 							.parse(page, | 
					
						
							| 
									
										
										
										
											2016-07-27 00:08:11 +03:00
										 |  |  | 								page.raw,  | 
					
						
							|  |  |  | 								{ slots: state.slots },  | 
					
						
							|  |  |  | 								true))) | 
					
						
							|  |  |  | 					.html() | 
					
						
							| 
									
										
										
										
											2016-07-26 07:53:44 +03:00
										 |  |  | 			})) | 
					
						
							| 
									
										
										
										
											2016-07-26 07:07:51 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-07-28 09:07:46 +03:00
										 |  |  | 		// post processing...
 | 
					
						
							| 
									
										
										
										
											2016-07-26 07:07:51 +03:00
										 |  |  | 		if(!skip_post){ | 
					
						
							| 
									
										
										
										
											2016-07-28 09:07:46 +03:00
										 |  |  | 			// fill slots...
 | 
					
						
							|  |  |  | 			// XXX need to prevent this from processing slots in editable
 | 
					
						
							|  |  |  | 			// 		elements...
 | 
					
						
							|  |  |  | 			slots = {} | 
					
						
							|  |  |  | 			// get slots...
 | 
					
						
							|  |  |  | 			parsed.find('slot') | 
					
						
							|  |  |  | 				.each(function(i, e){ | 
					
						
							|  |  |  | 					e = $(e) | 
					
						
							|  |  |  | 					var n = e.attr('name') | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 					n in slots && e.detach() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 					slots[n] = e  | 
					
						
							|  |  |  | 				}) | 
					
						
							|  |  |  | 			// place slots...
 | 
					
						
							|  |  |  | 			parsed.find('slot') | 
					
						
							|  |  |  | 				.each(function(i, e){ | 
					
						
							|  |  |  | 					e = $(e) | 
					
						
							|  |  |  | 					var n = e.attr('name') | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 					e.replaceWith(slots[n]) | 
					
						
							|  |  |  | 				}) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			// post-macro...
 | 
					
						
							|  |  |  | 			this.post_macro  | 
					
						
							|  |  |  | 				&& _parse(context, parsed, this.post_macro) | 
					
						
							| 
									
										
										
										
											2016-07-26 07:07:51 +03:00
										 |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-07-26 07:53:44 +03:00
										 |  |  | 		// XXX shuld we get rid of the rot span???
 | 
					
						
							| 
									
										
										
										
											2016-07-26 07:07:51 +03:00
										 |  |  | 		return parsed | 
					
						
							| 
									
										
										
										
											2016-07-25 22:08:44 +03:00
										 |  |  | 	}, | 
					
						
							| 
									
										
										
										
											2016-07-19 03:10:16 +03:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											2016-07-17 15:58:50 +03:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-07-04 19:51:37 +03:00
										 |  |  | 
 | 
					
						
							|  |  |  | /*********************************************************************/ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-07-09 21:40:48 +03:00
										 |  |  | // XXX not sure about these...
 | 
					
						
							| 
									
										
										
										
											2016-07-19 02:23:28 +03:00
										 |  |  | // XXX add docs...
 | 
					
						
							| 
									
										
										
										
											2016-07-09 21:40:48 +03:00
										 |  |  | var BaseData = { | 
					
						
							| 
									
										
										
										
											2016-07-22 21:46:23 +03:00
										 |  |  | 	// Macro acces to standard page attributes (paths)...
 | 
					
						
							|  |  |  | 	'System/title': function(){ return '['+ this.get('..').title +']' }, | 
					
						
							|  |  |  | 	'System/path': function(){ return '['+ this.dir +']' }, | 
					
						
							|  |  |  | 	'System/dir': function(){ return '['+ this.get('..').dir +']' }, | 
					
						
							|  |  |  | 	'System/location': function(){ return '['+ this.dir +']' }, | 
					
						
							|  |  |  | 	'System/resolved': function(){ return '['+ this.get('..').acquire() +']' }, | 
					
						
							| 
									
										
										
										
											2016-07-10 04:30:52 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-07-19 03:10:16 +03:00
										 |  |  | 	// page data...
 | 
					
						
							| 
									
										
										
										
											2016-07-20 17:16:49 +03:00
										 |  |  | 	//
 | 
					
						
							|  |  |  | 	// NOTE: special case: ./raw is treated a differently when getting .text
 | 
					
						
							|  |  |  | 	// 		i.e:
 | 
					
						
							|  |  |  | 	// 			.get('./raw').text
 | 
					
						
							|  |  |  | 	// 		is the same as:
 | 
					
						
							|  |  |  | 	// 			.get('.').raw
 | 
					
						
							| 
									
										
										
										
											2016-07-19 03:10:16 +03:00
										 |  |  | 	'System/raw': function(){ return this.get('..').raw }, | 
					
						
							|  |  |  | 	'System/text': function(){ return this.get('..').text }, | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-07-19 20:42:33 +03:00
										 |  |  | 	// XXX move this to Wiki.children + rename...
 | 
					
						
							| 
									
										
										
										
											2016-07-11 04:32:56 +03:00
										 |  |  | 	'System/list': function(){ | 
					
						
							| 
									
										
										
										
											2016-07-09 21:40:48 +03:00
										 |  |  | 		var p = this.dir | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		return Object.keys(this.__wiki_data) | 
					
						
							|  |  |  | 			.map(function(k){ | 
					
						
							|  |  |  | 				if(k.indexOf(p) == 0){ | 
					
						
							|  |  |  | 					return path2lst(k.slice(p.length)).shift() | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 				return null | 
					
						
							|  |  |  | 			}) | 
					
						
							| 
									
										
										
										
											2016-07-19 03:10:16 +03:00
										 |  |  | 			.filter(function(e){ return e != null }) | 
					
						
							| 
									
										
										
										
											2016-07-10 03:29:53 +03:00
										 |  |  | 			.sort() | 
					
						
							| 
									
										
										
										
											2016-07-19 03:10:16 +03:00
										 |  |  | 			.map(function(e){ return '['+ e +']' }) | 
					
						
							| 
									
										
										
										
											2016-07-09 21:40:48 +03:00
										 |  |  | 			.join('<br>') | 
					
						
							|  |  |  | 	}, | 
					
						
							| 
									
										
										
										
											2016-07-11 04:32:56 +03:00
										 |  |  | 	'System/tree': function(){ | 
					
						
							| 
									
										
										
										
											2016-07-09 21:40:48 +03:00
										 |  |  | 		var p = this.dir | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		return Object.keys(this.__wiki_data) | 
					
						
							|  |  |  | 			.map(function(k){ | 
					
						
							|  |  |  | 				if(k.indexOf(p) == 0){ | 
					
						
							|  |  |  | 					return k | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 				return null | 
					
						
							|  |  |  | 			}) | 
					
						
							| 
									
										
										
										
											2016-07-19 03:10:16 +03:00
										 |  |  | 			.filter(function(e){ return e != null }) | 
					
						
							| 
									
										
										
										
											2016-07-10 03:29:53 +03:00
										 |  |  | 			.sort() | 
					
						
							| 
									
										
										
										
											2016-07-19 03:10:16 +03:00
										 |  |  | 			.map(function(e){ return '['+ e +']' }) | 
					
						
							| 
									
										
										
										
											2016-07-09 21:40:48 +03:00
										 |  |  | 			.join('<br>') | 
					
						
							|  |  |  | 	}, | 
					
						
							| 
									
										
										
										
											2016-07-19 03:10:16 +03:00
										 |  |  | 	// list links to this page...
 | 
					
						
							| 
									
										
										
										
											2016-07-11 04:32:56 +03:00
										 |  |  | 	'System/links': function(){ | 
					
						
							| 
									
										
										
										
											2016-07-09 21:40:48 +03:00
										 |  |  | 		var that = this | 
					
						
							|  |  |  | 		var p = this.dir | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		var res = [] | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		var wiki = this.__wiki_data | 
					
						
							|  |  |  | 		Object.keys(wiki).forEach(function(k){ | 
					
						
							|  |  |  | 			(wiki[k].links || []).forEach(function(l){ | 
					
						
							| 
									
										
										
										
											2016-07-11 18:41:23 +03:00
										 |  |  | 				(l == p || that.get(path2lst(l).slice(0, -1)).acquire('./'+path2lst(l).pop()) == p) | 
					
						
							| 
									
										
										
										
											2016-07-09 21:40:48 +03:00
										 |  |  | 					&& res.push([l, k]) | 
					
						
							|  |  |  | 			}) | 
					
						
							|  |  |  | 		}) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		return res | 
					
						
							| 
									
										
										
										
											2016-07-19 03:10:16 +03:00
										 |  |  | 			//.map(function(e){ return '['+ e[0] +'] <i>from page: ['+ e[1] +']</i>' })
 | 
					
						
							|  |  |  | 			.map(function(e){ return '['+ e[1] +'] <i>-> ['+ e[0] +']</i>' }) | 
					
						
							| 
									
										
										
										
											2016-07-10 03:29:53 +03:00
										 |  |  | 			.sort() | 
					
						
							| 
									
										
										
										
											2016-07-09 21:40:48 +03:00
										 |  |  | 			.join('<br>') | 
					
						
							|  |  |  | 	}, | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// XXX this needs a redirect...
 | 
					
						
							| 
									
										
										
										
											2016-07-11 04:32:56 +03:00
										 |  |  | 	'System/delete': function(){ | 
					
						
							| 
									
										
										
										
											2016-07-09 21:40:48 +03:00
										 |  |  | 		var p = this.dir | 
					
						
							|  |  |  | 		delete this.__wiki_data[p] | 
					
						
							|  |  |  | 	}, | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-07-04 19:51:37 +03:00
										 |  |  | 
 | 
					
						
							|  |  |  | // data store...
 | 
					
						
							|  |  |  | // Format:
 | 
					
						
							|  |  |  | // 	{
 | 
					
						
							|  |  |  | // 		<path>: {
 | 
					
						
							|  |  |  | // 			text: <text>,
 | 
					
						
							|  |  |  | //
 | 
					
						
							|  |  |  | // 			links: [
 | 
					
						
							|  |  |  | // 				<offset>: <link>,
 | 
					
						
							|  |  |  | // 			],
 | 
					
						
							|  |  |  | // 		}
 | 
					
						
							|  |  |  | // 	}
 | 
					
						
							| 
									
										
										
										
											2016-07-19 02:23:28 +03:00
										 |  |  | //
 | 
					
						
							|  |  |  | // XXX add .json support...
 | 
					
						
							| 
									
										
										
										
											2016-07-04 19:51:37 +03:00
										 |  |  | var data = { | 
					
						
							| 
									
										
										
										
											2016-07-08 01:40:59 +03:00
										 |  |  | 	'Templates/EmptyPage': { | 
					
						
							| 
									
										
										
										
											2016-07-22 23:42:34 +03:00
										 |  |  | 		text: '' | 
					
						
							|  |  |  | 			+'<!-- place filters here so as not to takup page space: ... -->\n' | 
					
						
							|  |  |  | 			+'\n' | 
					
						
							|  |  |  | 			+'Page @include(./path) is empty.' +'<br><br>\n' | 
					
						
							|  |  |  | 			+'\n' | 
					
						
							|  |  |  | 			+'Links to this page:' +'<br>\n' | 
					
						
							|  |  |  | 			+'@include(./links)' +'<br><br>\n' | 
					
						
							|  |  |  | 			+'\n', | 
					
						
							| 
									
										
										
										
											2016-07-04 20:42:46 +03:00
										 |  |  | 	}, | 
					
						
							| 
									
										
										
										
											2016-07-12 03:22:06 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-07-22 23:42:34 +03:00
										 |  |  | 	'Templates/_raw': { | 
					
						
							|  |  |  | 		text: '@source(..)', | 
					
						
							|  |  |  | 	}, | 
					
						
							| 
									
										
										
										
											2016-07-28 09:07:46 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-07-12 03:22:06 +03:00
										 |  |  | 	'Templates/_view': { | 
					
						
							|  |  |  | 		text: '\n' | 
					
						
							| 
									
										
										
										
											2016-07-22 23:42:34 +03:00
										 |  |  | 			+'\n' | 
					
						
							| 
									
										
										
										
											2016-07-27 16:59:17 +03:00
										 |  |  | 			+'<div>\n' | 
					
						
							|  |  |  | 				+'<a href="#tree">☰</a> \n' | 
					
						
							| 
									
										
										
										
											2016-07-28 09:07:46 +03:00
										 |  |  | 				+'@include(../path)\n' | 
					
						
							|  |  |  | 				+'\n' | 
					
						
							|  |  |  | 				+'<slot name="toggle-edit-link">\n' | 
					
						
							|  |  |  | 					+'(<a href="#./_edit">edit</a>)\n' | 
					
						
							|  |  |  | 				+'</slot>\n' | 
					
						
							|  |  |  | 			+'\n' | 
					
						
							| 
									
										
										
										
											2016-07-27 16:59:17 +03:00
										 |  |  | 			+'</div>\n' | 
					
						
							| 
									
										
										
										
											2016-07-12 03:22:06 +03:00
										 |  |  | 			+'<hr>\n' | 
					
						
							| 
									
										
										
										
											2016-07-27 02:13:15 +03:00
										 |  |  | 			+'<h1 class="title" contenteditable tabindex="0">' | 
					
						
							| 
									
										
										
										
											2016-07-28 09:07:46 +03:00
										 |  |  | 				+'<slot name="title">' | 
					
						
							|  |  |  | 					+'@source(../title)' | 
					
						
							|  |  |  | 				+'</slot>' | 
					
						
							|  |  |  | 			+'\n' | 
					
						
							| 
									
										
										
										
											2016-07-27 02:13:15 +03:00
										 |  |  | 			+'</h1>\n' | 
					
						
							| 
									
										
										
										
											2016-07-12 03:22:06 +03:00
										 |  |  | 			+'<br>\n' | 
					
						
							| 
									
										
										
										
											2016-07-28 09:07:46 +03:00
										 |  |  | 			+'\n' | 
					
						
							|  |  |  | 			+'<slot name="page-content">\n' | 
					
						
							|  |  |  | 				+'<include src=".." class="text" saveto=".." tabindex="0"/>\n' | 
					
						
							|  |  |  | 			+'</slot>\n' | 
					
						
							|  |  |  | 			+'\n' | 
					
						
							| 
									
										
										
										
											2016-07-22 23:42:34 +03:00
										 |  |  | 			+'<hr>\n' | 
					
						
							| 
									
										
										
										
											2016-07-23 05:04:38 +03:00
										 |  |  | 			+'<a href="#/">home</a>\n' | 
					
						
							| 
									
										
										
										
											2016-07-12 03:22:06 +03:00
										 |  |  | 			+'\n', | 
					
						
							|  |  |  | 	}, | 
					
						
							|  |  |  | 	'Templates/_edit': { | 
					
						
							|  |  |  | 		text: '\n' | 
					
						
							| 
									
										
										
										
											2016-07-22 23:42:34 +03:00
										 |  |  | 			+'<!-- @filter(-wikiword) -->\n' | 
					
						
							|  |  |  | 			+'\n' | 
					
						
							| 
									
										
										
										
											2016-07-28 09:07:46 +03:00
										 |  |  | 			+'<include src="../_view"/>\n' | 
					
						
							|  |  |  | 			+'\n' | 
					
						
							|  |  |  | 			+'<slot name="toggle-edit-link">' | 
					
						
							|  |  |  | 				+'(<a href="#..">view</a>)' | 
					
						
							|  |  |  | 			+'</slot>\n' | 
					
						
							|  |  |  | 			+'\n' | 
					
						
							|  |  |  | 			+'<slot name="page-content">\n' | 
					
						
							|  |  |  | 				+'<code><pre>' | 
					
						
							|  |  |  | 					+'<quote src="../raw" class="raw" saveto=".." contenteditable/>' | 
					
						
							|  |  |  | 				+'</pre></code>\n' | 
					
						
							|  |  |  | 			+'</slot>' | 
					
						
							| 
									
										
										
										
											2016-07-12 03:22:06 +03:00
										 |  |  | 			+'', | 
					
						
							|  |  |  | 	}, | 
					
						
							| 
									
										
										
										
											2016-07-04 19:51:37 +03:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											2016-07-09 21:40:48 +03:00
										 |  |  | data.__proto__ = BaseData | 
					
						
							| 
									
										
										
										
											2016-07-04 19:51:37 +03:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-07-09 19:16:25 +03:00
										 |  |  | 
 | 
					
						
							|  |  |  | /*********************************************************************/ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-07-19 02:23:28 +03:00
										 |  |  | // XXX add .json support...
 | 
					
						
							| 
									
										
										
										
											2016-07-04 19:51:37 +03:00
										 |  |  | var Wiki = { | 
					
						
							| 
									
										
										
										
											2016-07-04 20:42:46 +03:00
										 |  |  | 	__wiki_data: data, | 
					
						
							| 
									
										
										
										
											2016-07-04 19:51:37 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-07-27 02:13:15 +03:00
										 |  |  | 	__config_page__: 'System/Settings', | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-07-05 16:58:04 +03:00
										 |  |  | 	__home_page__: 'WikiHome', | 
					
						
							| 
									
										
										
										
											2016-07-27 02:13:15 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-07-08 01:40:59 +03:00
										 |  |  | 	__default_page__: 'EmptyPage', | 
					
						
							| 
									
										
										
										
											2016-07-27 02:13:15 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-07-11 17:57:28 +03:00
										 |  |  | 	// Special sub-paths to look in on each level...
 | 
					
						
							| 
									
										
										
										
											2016-07-11 04:32:56 +03:00
										 |  |  | 	__acquesition_order__: [ | 
					
						
							|  |  |  | 		'Templates', | 
					
						
							|  |  |  | 	], | 
					
						
							| 
									
										
										
										
											2016-07-27 02:13:15 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-07-11 17:57:28 +03:00
										 |  |  | 	__post_acquesition_order__: [ | 
					
						
							|  |  |  | 	], | 
					
						
							| 
									
										
										
										
											2016-07-27 02:13:15 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-07-11 04:32:56 +03:00
										 |  |  | 	// XXX should this be read only???
 | 
					
						
							|  |  |  | 	__system__: 'System', | 
					
						
							| 
									
										
										
										
											2016-07-09 19:16:25 +03:00
										 |  |  | 	//__redirect_template__: 'RedirectTemplate',
 | 
					
						
							| 
									
										
										
										
											2016-07-05 16:58:04 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-07-07 22:21:04 +03:00
										 |  |  | 	__wiki_link__: RegExp('('+[ | 
					
						
							| 
									
										
										
										
											2016-07-09 19:16:25 +03:00
										 |  |  | 		'(\\./|\\.\\./|[A-Z][a-z0-9]+[A-Z/])[a-zA-Z0-9/]*', | 
					
						
							| 
									
										
										
										
											2016-07-07 22:21:04 +03:00
										 |  |  | 		'\\[[^\\]]+\\]', | 
					
						
							|  |  |  | 	].join('|') +')', 'g'), | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-07-27 00:10:14 +03:00
										 |  |  | 	__macro_parser__: macro, | 
					
						
							| 
									
										
										
										
											2016-07-27 00:08:11 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-07-05 16:58:04 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-07-09 19:16:25 +03:00
										 |  |  | 	// Resolve '.' and '..' relative to current page...
 | 
					
						
							|  |  |  | 	//
 | 
					
						
							| 
									
										
										
										
											2016-07-10 04:30:52 +03:00
										 |  |  | 	// NOTE: '.' is relative to .path and not to .dir
 | 
					
						
							| 
									
										
										
										
											2016-07-12 03:22:06 +03:00
										 |  |  | 	// NOTE: this is a method as it needs the context to resolve...
 | 
					
						
							| 
									
										
										
										
											2016-07-09 19:16:25 +03:00
										 |  |  | 	resolveDotPath: function(path){ | 
					
						
							|  |  |  | 		path = normalizePath(path) | 
					
						
							|  |  |  | 		// '.' or './*'
 | 
					
						
							|  |  |  | 		return path == '.' || /^\.\//.test(path) ?  | 
					
						
							| 
									
										
										
										
											2016-07-10 04:30:52 +03:00
										 |  |  | 				//path.replace(/^\./, this.dir)
 | 
					
						
							|  |  |  | 				path.replace(/^\./, this.path) | 
					
						
							| 
									
										
										
										
											2016-07-09 19:16:25 +03:00
										 |  |  | 			// '..' or '../*'
 | 
					
						
							|  |  |  | 			: path == '..' || /^\.\.\//.test(path) ?  | 
					
						
							| 
									
										
										
										
											2016-07-10 04:30:52 +03:00
										 |  |  | 				//path.replace(/^\.\./, 
 | 
					
						
							|  |  |  | 				//	normalizePath(path2lst(this.dir).slice(0, -1)))
 | 
					
						
							|  |  |  | 				path.replace(/^\.\./, this.dir) | 
					
						
							| 
									
										
										
										
											2016-07-09 19:16:25 +03:00
										 |  |  | 			: path | 
					
						
							|  |  |  | 	}, | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-07-04 20:42:46 +03:00
										 |  |  | 	// current location...
 | 
					
						
							| 
									
										
										
										
											2016-07-04 19:51:37 +03:00
										 |  |  | 	get location(){ | 
					
						
							| 
									
										
										
										
											2016-07-05 16:58:04 +03:00
										 |  |  | 		return this.__location || this.__home_page__ }, | 
					
						
							| 
									
										
										
										
											2016-07-04 19:51:37 +03:00
										 |  |  | 	set location(value){ | 
					
						
							| 
									
										
										
										
											2016-07-09 19:16:25 +03:00
										 |  |  | 		this.__location = this.resolveDotPath(value) }, | 
					
						
							| 
									
										
										
										
											2016-07-04 19:51:37 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-07-11 18:41:23 +03:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	get data(){ | 
					
						
							|  |  |  | 		return this.__wiki_data[this.acquire()] }, | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-07-27 02:13:15 +03:00
										 |  |  | 	// XXX experimental...
 | 
					
						
							| 
									
										
										
										
											2016-07-22 21:46:23 +03:00
										 |  |  | 	get config(){ | 
					
						
							| 
									
										
										
										
											2016-07-27 03:19:01 +03:00
										 |  |  | 		try{ | 
					
						
							|  |  |  | 			return JSON.parse(this.get(this.__config_page__).code) || {} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		} catch(err){ | 
					
						
							|  |  |  | 			console.error('CONFIG:', err) | 
					
						
							|  |  |  | 			return {} | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	}, | 
					
						
							| 
									
										
										
										
											2016-07-22 21:46:23 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-07-11 18:41:23 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-07-19 02:40:51 +03:00
										 |  |  | 	// XXX
 | 
					
						
							|  |  |  | 	clone: function(){ | 
					
						
							|  |  |  | 		var o = Object.create(Wiki) | 
					
						
							|  |  |  | 		o.location = this.location | 
					
						
							|  |  |  | 		return o | 
					
						
							|  |  |  | 	}, | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-07-04 20:42:46 +03:00
										 |  |  | 	// page path...
 | 
					
						
							|  |  |  | 	//
 | 
					
						
							|  |  |  | 	// Format:
 | 
					
						
							|  |  |  | 	// 	<dir>/<title>
 | 
					
						
							|  |  |  | 	//
 | 
					
						
							|  |  |  | 	// NOTE: changing this will move the page to the new path and change
 | 
					
						
							|  |  |  | 	// 		.location acordingly...
 | 
					
						
							|  |  |  | 	// NOTE: same applies to path parts below...
 | 
					
						
							| 
									
										
										
										
											2016-07-11 19:22:00 +03:00
										 |  |  | 	// NOTE: changing path will update all the links to the moving page.
 | 
					
						
							|  |  |  | 	// NOTE: if a link can't be updated without a conflit then it is left
 | 
					
						
							|  |  |  | 	// 		unchanged, and a redirect page will be created.
 | 
					
						
							| 
									
										
										
										
											2016-07-04 20:42:46 +03:00
										 |  |  | 	get path(){  | 
					
						
							|  |  |  | 		return this.location }, | 
					
						
							| 
									
										
										
										
											2016-07-11 19:22:00 +03:00
										 |  |  | 	// XXX should lik updating be part of this???
 | 
					
						
							|  |  |  | 	// XXX use a template for the redirect page...
 | 
					
						
							| 
									
										
										
										
											2016-07-04 19:51:37 +03:00
										 |  |  | 	set path(value){ | 
					
						
							| 
									
										
										
										
											2016-07-09 19:16:25 +03:00
										 |  |  | 		value = this.resolveDotPath(value) | 
					
						
							| 
									
										
										
										
											2016-07-04 20:42:46 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-07-09 06:26:16 +03:00
										 |  |  | 		var l = this.location | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		if(value == l){ | 
					
						
							|  |  |  | 			return | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		// old...
 | 
					
						
							|  |  |  | 		var otitle = this.title | 
					
						
							|  |  |  | 		var odir = this.dir | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-07-08 01:40:59 +03:00
										 |  |  | 		if(this.exists(l)){ | 
					
						
							|  |  |  | 			this.__wiki_data[value] = this.__wiki_data[l] | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2016-07-04 20:42:46 +03:00
										 |  |  | 		this.location = value | 
					
						
							| 
									
										
										
										
											2016-07-08 01:40:59 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-07-09 06:26:16 +03:00
										 |  |  | 		// new...
 | 
					
						
							|  |  |  | 		var ntitle = this.title | 
					
						
							|  |  |  | 		var ndir = this.dir | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		var redirect = false | 
					
						
							| 
									
										
										
										
											2016-07-08 01:40:59 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-07-09 06:26:16 +03:00
										 |  |  | 		// update links to this page...
 | 
					
						
							| 
									
										
										
										
											2016-07-08 01:40:59 +03:00
										 |  |  | 		this.pages(function(page){ | 
					
						
							| 
									
										
										
										
											2016-07-09 06:26:16 +03:00
										 |  |  | 			// skip the old page...
 | 
					
						
							|  |  |  | 			if(page.location == l){ | 
					
						
							|  |  |  | 				return | 
					
						
							|  |  |  | 			} | 
					
						
							| 
									
										
										
										
											2016-07-12 03:22:06 +03:00
										 |  |  | 			page.raw = page.raw.replace(page.__wiki_link__, function(lnk){ | 
					
						
							| 
									
										
										
										
											2016-07-09 06:26:16 +03:00
										 |  |  | 				var from = lnk[0] == '[' ? lnk.slice(1, -1) : lnk | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 				// get path/title...
 | 
					
						
							|  |  |  | 				var p = path2lst(from) | 
					
						
							| 
									
										
										
										
											2016-07-08 01:40:59 +03:00
										 |  |  | 				var t = p.pop() | 
					
						
							| 
									
										
										
										
											2016-07-09 06:26:16 +03:00
										 |  |  | 				p = normalizePath(p) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-07-11 18:41:23 +03:00
										 |  |  | 				var target = page.get(p).acquire('./'+t) | 
					
						
							| 
									
										
										
										
											2016-07-09 06:26:16 +03:00
										 |  |  | 				// page target changed...
 | 
					
						
							|  |  |  | 				// NOTE: this can happen either when a link was an orphan
 | 
					
						
							|  |  |  | 				// 		or if the new page path shadowed the original 
 | 
					
						
							|  |  |  | 				// 		target...
 | 
					
						
							|  |  |  | 				// XXX should we report the exact condition here???
 | 
					
						
							|  |  |  | 				if(target == value){ | 
					
						
							|  |  |  | 					console.log('Link target changed:', lnk, '->', value) | 
					
						
							|  |  |  | 					return lnk | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 				// skip links that do not resolve to target...
 | 
					
						
							| 
									
										
										
										
											2016-07-11 18:41:23 +03:00
										 |  |  | 				} else if(page.get(p).acquire('./'+t) != l){ | 
					
						
							| 
									
										
										
										
											2016-07-09 06:26:16 +03:00
										 |  |  | 					return lnk | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 				// format the new link...
 | 
					
						
							|  |  |  | 				var to = p == '' ? ntitle : p +'/'+ ntitle | 
					
						
							|  |  |  | 				to = lnk[0] == '[' ? '['+to+'}' : to | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 				// explicit link change -- replace...
 | 
					
						
							|  |  |  | 				if(from == l){ | 
					
						
							|  |  |  | 					//console.log(lnk, '->', to)
 | 
					
						
							|  |  |  | 					return to | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 				// path did not change -- change the title...
 | 
					
						
							|  |  |  | 				} else if(ndir == odir){ | 
					
						
							|  |  |  | 					// conflict: the new link will not resolve to the 
 | 
					
						
							|  |  |  | 					// 		target page...
 | 
					
						
							| 
									
										
										
										
											2016-07-11 18:41:23 +03:00
										 |  |  | 					if(page.get(p).acquire('./'+ntitle) != value){ | 
					
						
							| 
									
										
										
										
											2016-07-09 06:26:16 +03:00
										 |  |  | 						console.log('ERR:', lnk, '->', to, | 
					
						
							| 
									
										
										
										
											2016-07-11 18:41:23 +03:00
										 |  |  | 							'is shadowed by:', page.get(p).acquire('./'+ntitle)) | 
					
						
							| 
									
										
										
										
											2016-07-09 06:26:16 +03:00
										 |  |  | 						// XXX should we add a note to the link???
 | 
					
						
							|  |  |  | 						redirect = true | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 					// replace title...
 | 
					
						
							|  |  |  | 					} else { | 
					
						
							|  |  |  | 						//console.log(lnk, '->', to)
 | 
					
						
							|  |  |  | 						return to | 
					
						
							|  |  |  | 					} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 				// path changed -- keep link + add redirect page...
 | 
					
						
							|  |  |  | 				} else { | 
					
						
							|  |  |  | 					redirect = true | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 				// no change...
 | 
					
						
							|  |  |  | 				return lnk | 
					
						
							| 
									
										
										
										
											2016-07-08 01:40:59 +03:00
										 |  |  | 			}) | 
					
						
							|  |  |  | 		}) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-07-09 06:26:16 +03:00
										 |  |  | 		// redirect...
 | 
					
						
							|  |  |  | 		//
 | 
					
						
							|  |  |  | 		// XXX should we use a template here???
 | 
					
						
							|  |  |  | 		// 		...might be a good idea to set a .redirect attr and either
 | 
					
						
							|  |  |  | 		// 		do an internal/transparent redirect or show a redirect 
 | 
					
						
							|  |  |  | 		// 		template
 | 
					
						
							|  |  |  | 		// 		...might also be good to add an option to fix the link from
 | 
					
						
							|  |  |  | 		// 		the redirect page...
 | 
					
						
							|  |  |  | 		if(redirect){ | 
					
						
							|  |  |  | 			console.log('CREATING REDIRECT PAGE:', l, '->', value, '') | 
					
						
							| 
									
										
										
										
											2016-07-12 03:22:06 +03:00
										 |  |  | 			this.__wiki_data[l].raw = 'REDIRECT TO: ' + value | 
					
						
							| 
									
										
										
										
											2016-07-09 06:26:16 +03:00
										 |  |  | 				+'<br>' | 
					
						
							|  |  |  | 				+'<br><i>NOTE: This page was created when renaming the target ' | 
					
						
							|  |  |  | 					+'page that resulted new link being broken (i.e. resolved ' | 
					
						
							|  |  |  | 					+'to a different page from the target)</i>' | 
					
						
							|  |  |  | 			this.__wiki_data[l].redirect = value | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-07-08 01:40:59 +03:00
										 |  |  | 		// cleaup...
 | 
					
						
							| 
									
										
										
										
											2016-07-09 06:26:16 +03:00
										 |  |  | 		} else { | 
					
						
							|  |  |  | 			delete this.__wiki_data[l] | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2016-07-04 19:51:37 +03:00
										 |  |  | 	}, | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-07-04 20:42:46 +03:00
										 |  |  | 	// path parts: directory...
 | 
					
						
							|  |  |  | 	//
 | 
					
						
							|  |  |  | 	// NOTE: see .path for details...
 | 
					
						
							|  |  |  | 	get dir(){ | 
					
						
							|  |  |  | 		return path2lst(this.location).slice(0, -1).join('/') }, | 
					
						
							|  |  |  | 	set dir(value){ | 
					
						
							|  |  |  | 		this.path = value +'/'+ this.title }, | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// path parts: title...
 | 
					
						
							|  |  |  | 	//
 | 
					
						
							|  |  |  | 	// NOTE: see .path for details...
 | 
					
						
							|  |  |  | 	get title(){  | 
					
						
							|  |  |  | 		return path2lst(this.location).pop() }, | 
					
						
							|  |  |  | 	set title(value){ | 
					
						
							|  |  |  | 		this.path = this.dir +'/'+ value }, | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// page content...
 | 
					
						
							| 
									
										
										
										
											2016-07-12 03:22:06 +03:00
										 |  |  | 	get raw(){ | 
					
						
							| 
									
										
										
										
											2016-07-11 17:57:28 +03:00
										 |  |  | 		var data = this.data | 
					
						
							| 
									
										
										
										
											2016-07-09 21:40:48 +03:00
										 |  |  | 		return data instanceof Function ? data.call(this, this) | 
					
						
							|  |  |  | 			: typeof(data) == typeof('str') ? data | 
					
						
							|  |  |  | 			: data != null ? data.text | 
					
						
							|  |  |  | 			: '' | 
					
						
							|  |  |  | 	}, | 
					
						
							| 
									
										
										
										
											2016-07-12 03:22:06 +03:00
										 |  |  | 	set raw(value){ | 
					
						
							| 
									
										
										
										
											2016-07-04 20:42:46 +03:00
										 |  |  | 		var l = this.location | 
					
						
							| 
									
										
										
										
											2016-07-09 21:40:48 +03:00
										 |  |  | 
 | 
					
						
							|  |  |  | 		// prevent overwriting actions...
 | 
					
						
							| 
									
										
										
										
											2016-07-11 17:57:28 +03:00
										 |  |  | 		if(this.data instanceof Function){ | 
					
						
							| 
									
										
										
										
											2016-07-09 21:40:48 +03:00
										 |  |  | 			return | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-07-04 20:42:46 +03:00
										 |  |  | 		this.__wiki_data[l] = this.__wiki_data[l] || {} | 
					
						
							|  |  |  | 		this.__wiki_data[l].text = value | 
					
						
							| 
									
										
										
										
											2016-07-07 22:21:04 +03:00
										 |  |  | 
 | 
					
						
							|  |  |  | 		// cache links...
 | 
					
						
							| 
									
										
										
										
											2016-07-08 01:40:59 +03:00
										 |  |  | 		delete this.__wiki_data[l].links | 
					
						
							| 
									
										
										
										
											2016-07-07 22:21:04 +03:00
										 |  |  | 		this.__wiki_data[l].links = this.links | 
					
						
							| 
									
										
										
										
											2016-07-04 19:51:37 +03:00
										 |  |  | 	}, | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-07-21 16:24:45 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-07-27 02:13:15 +03:00
										 |  |  | 	get text(){ | 
					
						
							|  |  |  | 		//return this.parse() 
 | 
					
						
							| 
									
										
										
										
											2016-07-21 16:24:45 +03:00
										 |  |  | 		// special case: if we are getting ./raw then do not parse text...
 | 
					
						
							|  |  |  | 		return this.title == 'raw' ? this.raw  | 
					
						
							| 
									
										
										
										
											2016-07-27 02:13:15 +03:00
										 |  |  | 			: this.__macro_parser__.parse(this, this.raw) }, | 
					
						
							|  |  |  | 	get code(){ | 
					
						
							|  |  |  | 		return this.text.html() }, | 
					
						
							| 
									
										
										
										
											2016-07-19 23:13:51 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-07-12 03:22:06 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-07-08 01:40:59 +03:00
										 |  |  | 	// NOTE: this is set by setting .text
 | 
					
						
							| 
									
										
										
										
											2016-07-04 20:42:46 +03:00
										 |  |  | 	get links(){ | 
					
						
							| 
									
										
										
										
											2016-07-11 17:57:28 +03:00
										 |  |  | 		var data = this.data || {} | 
					
						
							| 
									
										
										
										
											2016-07-08 01:40:59 +03:00
										 |  |  | 		var links = data.links = data.links | 
					
						
							| 
									
										
										
										
											2016-07-12 03:22:06 +03:00
										 |  |  | 			|| (this.raw.match(this.__wiki_link__) || []) | 
					
						
							| 
									
										
										
										
											2016-07-07 22:21:04 +03:00
										 |  |  | 				// unwrap explicit links...
 | 
					
						
							| 
									
										
										
										
											2016-07-19 03:10:16 +03:00
										 |  |  | 				.map(function(e){ return e[0] == '[' ? e.slice(1, -1) : e }) | 
					
						
							| 
									
										
										
										
											2016-07-07 22:21:04 +03:00
										 |  |  | 				// unique...
 | 
					
						
							| 
									
										
										
										
											2016-07-19 03:10:16 +03:00
										 |  |  | 				.filter(function(e, i, l){ return l.slice(0, i).indexOf(e) == -1 }) | 
					
						
							| 
									
										
										
										
											2016-07-08 01:40:59 +03:00
										 |  |  | 		return links | 
					
						
							| 
									
										
										
										
											2016-07-04 20:42:46 +03:00
										 |  |  | 	}, | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-07-11 04:32:56 +03:00
										 |  |  | 	// navigation...
 | 
					
						
							|  |  |  | 	get parent(){ | 
					
						
							| 
									
										
										
										
											2016-07-12 03:22:06 +03:00
										 |  |  | 		return this.get('..') }, | 
					
						
							| 
									
										
										
										
											2016-07-19 03:10:16 +03:00
										 |  |  | 	// XXX list children/sub-pages...
 | 
					
						
							|  |  |  | 	get children(){ | 
					
						
							|  |  |  | 	}, | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-07-19 02:40:51 +03:00
										 |  |  | 	// XXX add prpper insyantiation ( .clone() )...
 | 
					
						
							| 
									
										
										
										
											2016-07-11 04:32:56 +03:00
										 |  |  | 	get: function(path){ | 
					
						
							| 
									
										
										
										
											2016-07-19 02:40:51 +03:00
										 |  |  | 		//var o = Object.create(this)
 | 
					
						
							|  |  |  | 		var o = this.clone()  | 
					
						
							| 
									
										
										
										
											2016-07-11 17:57:28 +03:00
										 |  |  | 		o.location = path || this.path | 
					
						
							| 
									
										
										
										
											2016-07-11 04:32:56 +03:00
										 |  |  | 		return o | 
					
						
							|  |  |  | 	}, | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-07-05 16:58:04 +03:00
										 |  |  | 	exists: function(path){ | 
					
						
							| 
									
										
										
										
											2016-07-12 03:22:06 +03:00
										 |  |  | 		return normalizePath(path || this.path) in this.__wiki_data }, | 
					
						
							| 
									
										
										
										
											2016-07-05 16:58:04 +03:00
										 |  |  | 	// get title from dir and then go up the tree...
 | 
					
						
							| 
									
										
										
										
											2016-07-19 02:23:28 +03:00
										 |  |  | 	//
 | 
					
						
							|  |  |  | 	// XXX should we also acquire each path part???
 | 
					
						
							| 
									
										
										
										
											2016-07-11 18:41:23 +03:00
										 |  |  | 	acquire: function(path, no_default){ | 
					
						
							| 
									
										
										
										
											2016-07-05 16:58:04 +03:00
										 |  |  | 		var that = this | 
					
						
							| 
									
										
										
										
											2016-07-11 18:41:23 +03:00
										 |  |  | 
 | 
					
						
							|  |  |  | 		// handle paths and relative paths...
 | 
					
						
							|  |  |  | 		var p = this.get(path) | 
					
						
							|  |  |  | 		var title = p.title | 
					
						
							|  |  |  | 		path = path2lst(p.dir) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-07-11 17:57:28 +03:00
										 |  |  | 		var acquire_from = this.__acquesition_order__ || [] | 
					
						
							|  |  |  | 		var post_acquire_from = this.__post_acquesition_order__ || [] | 
					
						
							|  |  |  | 		var data = this.__wiki_data | 
					
						
							| 
									
										
										
										
											2016-07-04 20:42:46 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-07-11 17:57:28 +03:00
										 |  |  | 		var _get = function(path, title, lst){ | 
					
						
							|  |  |  | 			lst = (lst == null || lst.length == 0) ? [''] : lst | 
					
						
							|  |  |  | 			for(var i=0; i < lst.length; i++){ | 
					
						
							|  |  |  | 				var p = path.concat([lst[i], title]) | 
					
						
							|  |  |  | 				if(that.exists(p)){ | 
					
						
							|  |  |  | 					p = normalizePath(p) | 
					
						
							|  |  |  | 					return that.__wiki_data[p] && p | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 			} | 
					
						
							| 
									
										
										
										
											2016-07-04 20:42:46 +03:00
										 |  |  | 		} | 
					
						
							| 
									
										
										
										
											2016-07-05 16:58:04 +03:00
										 |  |  | 
 | 
					
						
							|  |  |  | 		while(true){ | 
					
						
							|  |  |  | 			// get title from path...
 | 
					
						
							| 
									
										
										
										
											2016-07-11 17:57:28 +03:00
										 |  |  | 			var p = _get(path, title) | 
					
						
							|  |  |  | 				// get title from special paths in path...
 | 
					
						
							|  |  |  | 				|| _get(path, title, acquire_from) | 
					
						
							| 
									
										
										
										
											2016-07-05 16:58:04 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-07-11 17:57:28 +03:00
										 |  |  | 			if(p != null){ | 
					
						
							|  |  |  | 				return p | 
					
						
							| 
									
										
										
										
											2016-07-05 16:58:04 +03:00
										 |  |  | 			} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			if(path.length == 0){ | 
					
						
							| 
									
										
										
										
											2016-07-11 04:32:56 +03:00
										 |  |  | 				break | 
					
						
							| 
									
										
										
										
											2016-07-05 16:58:04 +03:00
										 |  |  | 			} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			path.pop() | 
					
						
							| 
									
										
										
										
											2016-07-04 20:42:46 +03:00
										 |  |  | 		} | 
					
						
							| 
									
										
										
										
											2016-07-11 04:32:56 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-07-11 17:57:28 +03:00
										 |  |  | 		// default paths...
 | 
					
						
							|  |  |  | 		var p = _get(path, title, post_acquire_from) | 
					
						
							|  |  |  | 			// system path...
 | 
					
						
							|  |  |  | 			|| this.__system__  | 
					
						
							|  |  |  | 				&& _get([this.__system__], title) | 
					
						
							| 
									
										
										
										
											2016-07-07 22:21:04 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-07-11 17:57:28 +03:00
										 |  |  | 		// NOTE: this may be null...
 | 
					
						
							|  |  |  | 		return p  | 
					
						
							| 
									
										
										
										
											2016-07-11 19:22:00 +03:00
										 |  |  | 			|| ((!no_default && title != this.__default_page__) ?  | 
					
						
							|  |  |  | 				this.acquire('./'+this.__default_page__)  | 
					
						
							|  |  |  | 				: null) | 
					
						
							| 
									
										
										
										
											2016-07-08 01:40:59 +03:00
										 |  |  | 	}, | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-07-05 16:58:04 +03:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	// serialization...
 | 
					
						
							| 
									
										
										
										
											2016-07-12 03:22:06 +03:00
										 |  |  | 	// XXX
 | 
					
						
							| 
									
										
										
										
											2016-07-05 16:58:04 +03:00
										 |  |  | 	json: function(path){ | 
					
						
							|  |  |  | 		return path == null ? JSON.parse(JSON.stringify(this.__wiki_data)) | 
					
						
							|  |  |  | 			: path == '.' ? { | 
					
						
							|  |  |  | 					path: this.location, | 
					
						
							| 
									
										
										
										
											2016-07-12 03:22:06 +03:00
										 |  |  | 					text: this.raw, | 
					
						
							| 
									
										
										
										
											2016-07-05 16:58:04 +03:00
										 |  |  | 				} | 
					
						
							|  |  |  | 			: { | 
					
						
							|  |  |  | 				path: path, | 
					
						
							| 
									
										
										
										
											2016-07-12 03:22:06 +03:00
										 |  |  | 				text: (this.__wiki_data[path] || {}).raw, | 
					
						
							| 
									
										
										
										
											2016-07-05 16:58:04 +03:00
										 |  |  | 			} | 
					
						
							|  |  |  | 	}, | 
					
						
							|  |  |  | 	// XXX should we inherit from the default???
 | 
					
						
							|  |  |  | 	load: function(json){ | 
					
						
							|  |  |  | 		this.__wiki_data = json | 
					
						
							|  |  |  | 	}, | 
					
						
							| 
									
										
										
										
											2016-07-08 01:40:59 +03:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// iteration...
 | 
					
						
							|  |  |  | 	// XXX this is not page specific, might need refactoring...
 | 
					
						
							|  |  |  | 	pages: function(callback){ | 
					
						
							|  |  |  | 		var that = this | 
					
						
							|  |  |  | 		Object.keys(this.__wiki_data).forEach(function(location){ | 
					
						
							|  |  |  | 			// XXX not sure if this is the right way to go...
 | 
					
						
							| 
									
										
										
										
											2016-07-19 02:40:51 +03:00
										 |  |  | 			//var o = Object.create(that)
 | 
					
						
							|  |  |  | 			var o = that.clone()  | 
					
						
							| 
									
										
										
										
											2016-07-08 01:40:59 +03:00
										 |  |  | 			o.location = location | 
					
						
							|  |  |  | 			callback.call(o, o) | 
					
						
							|  |  |  | 		}) | 
					
						
							|  |  |  | 		return this | 
					
						
							|  |  |  | 	}, | 
					
						
							| 
									
										
										
										
											2016-07-04 19:51:37 +03:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-07-13 05:06:54 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-07-04 19:51:37 +03:00
										 |  |  | /********************************************************************** | 
					
						
							|  |  |  | * vim:set ts=4 sw=4 :                                                */ |