diff --git a/index.html b/index.html index ea075d9..1ca34f4 100755 --- a/index.html +++ b/index.html @@ -71,10 +71,12 @@ var update_editor = function(){ var to = $(this).attr('saveto') || '.' console.log('SAVING:', Wiki.get(to).path) - Wiki.get(to).raw = clearWikiWords( + /*Wiki.get(to).raw = clearWikiWords( $('.text').clone()) .html() - /*// show \n in the inline editor... + //*/ + /* + // show \n in the inline editor... Wiki.get(to).raw = clearWikiWords( $('.text').clone() .find('.tmp-br') @@ -114,6 +116,34 @@ var update_editor = function(){ //.text($('.raw').html()) //raw.text(Wiki.get(raw.attr('saveto')).raw) + + $('include') + .attr('tabindex', 0) + .click(function(){ + event.stopPropagation() + }) + .focus(function(){ + var to = $(this).attr('src') || '.' + var page = Wiki.get(to) + console.log('EDITING:', page.path) + + // XXX select editor based on filters... + $(this) + //.html(page.text) + .html($('
')
+					.text(page.raw))
+		})
+		.on('keyup', function(){ 
+			var to = Wiki.get($(this).attr('src') || '.').path
+			console.log('SAVING:', to)
+			//Wiki.get(to).raw = $(this).text()
+			//Wiki.get(to).raw = $(this)[0].innerText
+		})
+		// XXX do this live, but on a timeout after user input...
+		// XXX need to place the cursor in the same position...
+		.blur(() => { 
+			reload() 
+		})
 }
 
 var go = (path) => {
diff --git a/wiki.js b/wiki.js
index 6ee69ab..211405a 100755
--- a/wiki.js
+++ b/wiki.js
@@ -7,6 +7,12 @@
 
 /*********************************************************************/
 // Hepers...
+//
+var quoteRegExp =
+RegExp.quoteRegExp =
+function(str){
+	return str.replace(/([\.\\\/\(\)\[\]\$\*\+\-\{\}\@\^\&\?\<\>])/g, '\\$1')
+}
 
 var path2lst = function(path){ 
 	return (path instanceof Array ?  path : path.split(/[\\\/]+/g))
@@ -157,7 +163,9 @@ var macro = {
 			function(context, elem, state){
 				var path = $(elem).attr('src')
 
-				return context.get(path).raw
+				return context.get(path)
+					.map(function(page){ return page.raw })
+					.join('\n')
 			}),
 
 		quote: Macro('Include quoted page source (without parsing)',
@@ -166,7 +174,13 @@ var macro = {
 				elem = $(elem)
 				var path = elem.attr('src')
 
-				return elem.text(context.get(path).raw)
+				return $(context.get(path)
+					.map(function(page){
+						return elem
+							.clone()
+							.attr('src', page.path)
+							.text(page.raw)[0]
+					}))
 			}),
 
 		/*
@@ -211,10 +225,42 @@ var macro = {
 				text = parse(elem)
 
 				elem.attr('text', null)
-				elem.html(text)
+				//elem.html(text)
 
 				return elem
 			}),
+
+		macro: Macro('Define/fill slot',
+			['name', 'src'],
+			function(context, elem, state, parse){
+				elem = $(elem)
+				var name = elem.attr('name')
+				var path = elem.attr('src')
+
+				state.templates = state.templates || {}
+
+
+				if(name){
+					if(elem.html().trim() != ''){
+						state.templates[name] = elem.clone()
+
+					} else if(name in state.templates) {
+						elem = state.templates[name]
+					}
+				}
+
+				if(path){
+					return $(context.get(path)
+						.map(function(page){
+							var e = elem.clone()
+								.attr('src', page.path)
+							parse(e, page)
+							return e[0]
+						}))
+				}
+
+				return ''
+			})
 	},
 	
 	// Post macros... 
@@ -354,9 +400,14 @@ var macro = {
 					// call macro...
 					var res = macro[name]
 						.call(that, context, elem, state,
-							function(elem){ _parse(context, elem, macro) })
+							function(elem, c){ 
+								return _parse(c || context, elem, macro) })
 
-					return res instanceof $ ? res[0].outerHTML 
+					return res instanceof jQuery ? 
+							// merge html of the returned set of elements...
+							res.map(function(i, e){ return e.outerHTML })
+								.toArray()
+								.join('\n')
 						: typeof(res) != typeof('str') ? res.outerHTML
 						: res
 				}
@@ -382,7 +433,8 @@ var macro = {
 					if(name in  macro){
 						$(e).replaceWith(macro[name]
 							.call(that, context, e, state, 
-								function(elem){ _parse(context, elem, macro) }))
+								function(elem, c){ 
+									return _parse(c || context, elem, macro) }))
 
 					// normal tag -> attrs + sub-tree...
 					} else {
@@ -444,17 +496,18 @@ var macro = {
 				var elem = $(page.shift())
 				page = page.pop()
 
-				return $('
') - .append(elem//$('') - .attr('src', page.path) - //.append(page - // .parse({ slots: state.slots }, true)) - .append(that - .parse(page, - page.raw, - { slots: state.slots }, - true))) - .html() + return page.map(function(page){ + return $('
') + .append(elem + .clone() + .attr('src', page.path) + .append(that + .parse(page, + page.raw, + { slots: state.slots }, + true))) + .html() + }).join('\n') })) // post processing... @@ -532,21 +585,6 @@ var BaseData = { .map(function(e){ return '['+ e +']' }) .join('
') }, - 'System/tree': function(){ - var p = this.dir - - return Object.keys(this.__wiki_data) - .map(function(k){ - if(k.indexOf(p) == 0){ - return k - } - return null - }) - .filter(function(e){ return e != null }) - .sort() - .map(function(e){ return '['+ e +']' }) - .join('
') - }, // list links to this page... 'System/links': function(){ var that = this @@ -602,6 +640,12 @@ var data = { +'\n', }, + 'Templates/pages': { + text: '' + +' @source(./path)
' + +'\n', + }, + 'Templates/_raw': { text: '@source(..)', }, @@ -706,6 +750,36 @@ var Wiki = { path.replace(/^\.\./, this.dir) : path }, + // Get list of paths resolving '*' and '**' + // + // XXX should we list parent pages??? + // XXX should this acquire stuff??? + resolveStarPath: function(path){ + // no pattern in path -> return as-is... + if(path.indexOf('*') < 0){ + return [ path ] + } + + // get the tail... + var tail = path.split(/\*/g).pop() + tail = tail == path ? '' : tail + + var pattern = RegExp('^' + +normalizePath(path) + // quote regexp chars... + .replace(/([\.\\\/\(\)\[\]\$\+\-\{\}\@\^\&\?\<\>])/g, '\\$1') + + // convert '*' and '**' to regexp... + .replace(/\*\*/g, '.*') + .replace(/^\*|([^.])\*/g, '$1[^\\/]*') + +'$') + + return Object.keys(this.__wiki_data) + .map(function(p){ return tail != '' ? + normalizePath(p +'/'+ tail) + : p }) + .filter(function(p){ return pattern.test(p) }) + }, // current location... @@ -734,6 +808,7 @@ var Wiki = { clone: function(){ var o = Object.create(Wiki) o.location = this.location + //o.__location_at = this.__location_at return o }, @@ -750,8 +825,8 @@ var Wiki = { // NOTE: if a link can't be updated without a conflit then it is left // unchanged, and a redirect page will be created. get path(){ - return this.location }, - // XXX should lik updating be part of this??? + return this.resolveStarPath(this.location)[this.at()] }, + // XXX should link updating be part of this??? // XXX use a template for the redirect page... set path(value){ value = this.resolveDotPath(value) @@ -868,7 +943,7 @@ var Wiki = { // // NOTE: see .path for details... get dir(){ - return path2lst(this.location).slice(0, -1).join('/') }, + return path2lst(this.path).slice(0, -1).join('/') }, set dir(value){ this.path = value +'/'+ this.title }, @@ -876,7 +951,7 @@ var Wiki = { // // NOTE: see .path for details... get title(){ - return path2lst(this.location).pop() }, + return path2lst(this.path).pop() }, set title(value){ this.path = this.dir +'/'+ value }, @@ -935,10 +1010,17 @@ var Wiki = { get children(){ }, + // NOTE: .get() is not the same as .clone() in that .get() will resolve + // the path to a specific location while .clone() will keep + // everything as-is... + // // XXX add prpper insyantiation ( .clone() )... get: function(path){ //var o = Object.create(this) var o = this.clone() + // NOTE: this is here to resolve path patterns... + o.location = this.path + o.location = path || this.path return o }, @@ -1003,7 +1085,66 @@ var Wiki = { }, + // iteration... + get length(){ + return this.resolveStarPath(this.location).length }, + // get/srt postion in list of pages... + // XXX do we need to min/max normalize n?? + at: function(n){ + // get position... + if(n == null){ + return this.__location_at || 0 + } + + var l = this.length + + // end of list... + if(n >= l || n < -l){ + return null + } + + var res = this.clone() + + n = n < 0 ? l - n : n + // XXX do we min/max n??? + n = Math.max(n, 0) + n = Math.min(l-1, n) + + res.__location_at = n + + return res + }, + prev: function(){ + var i = this.at() - 1 + // NOTE: need to guard against overflows... + return i >= 0 ? this.at(i) : null }, + next: function(){ + return this.at(this.at() + 1) }, + + map: function(func){ + var res = [] + for(var i=0; i < this.length; i++){ + var page = this.at(i) + res.push(func.call(page, page, i)) + } + return res + }, + filter: function(func){ + var res = [] + for(var i=0; i < this.length; i++){ + var page = this.at(i) + func.call(page, page, i) && res.push(page) + } + return res + }, + forEach: function(func){ + this.map(func) + return this + }, + + // serialization... + // XXX need to account for '*' and '**' in path... // XXX json: function(path){ return path == null ? JSON.parse(JSON.stringify(this.__wiki_data))