mirror of
				https://github.com/flynx/pWiki.git
				synced 2025-10-29 01:50:07 +00:00 
			
		
		
		
	
		
			
				
	
	
		
			282 lines
		
	
	
		
			6.0 KiB
		
	
	
	
		
			HTML
		
	
	
		
			Executable File
		
	
	
	
	
			
		
		
	
	
			282 lines
		
	
	
		
			6.0 KiB
		
	
	
	
		
			HTML
		
	
	
		
			Executable File
		
	
	
	
	
| <!DOCTYPE html>
 | |
| <html>
 | |
| <head>
 | |
| <title>pWiki</title>
 | |
| </head>
 | |
| <style>
 | |
| </style>
 | |
| 
 | |
| <script src="ext-lib/jquery.js"></script>
 | |
| <script src="wiki.js"></script>
 | |
| 
 | |
| <script>
 | |
| 
 | |
| var clear = () => {
 | |
| 	delete localStorage['wiki-data']
 | |
| 	delete localStorage['wiki-location']
 | |
| }
 | |
| 
 | |
| 
 | |
| var macro = {
 | |
| 	__macro__pattern__: null,
 | |
| 
 | |
| 	context: null,
 | |
| 
 | |
| 	filter: {
 | |
| 	},
 | |
| 	macro: {
 | |
| 		filter: function(args, text, filters){
 | |
| 			var filter = args[0] || args.name
 | |
| 
 | |
| 			filters.push(filter)
 | |
| 
 | |
| 			return ''
 | |
| 		},
 | |
| 		include: function(args){
 | |
| 			var path = args[0] || args.src
 | |
| 
 | |
| 			var text = this.context.get(path).text
 | |
| 
 | |
| 			// XXX get new context???
 | |
| 			return this.parse(text)
 | |
| 		},
 | |
| 		slot: function(args){
 | |
| 			// XXX processing stages: 
 | |
| 			//		- if we slot for first time return it as-is
 | |
| 			//		- if slot text available in slots us it to fill
 | |
| 			// 		- slot seen again, save text to slots but return ''
 | |
| 		},
 | |
| 	},
 | |
| 
 | |
| 	parseArgs: function(args){
 | |
| 		// XXX
 | |
| 	},
 | |
| 	parse: function(text){
 | |
| 		var that = this
 | |
| 		var filters = []
 | |
| 		var slots = {}
 | |
| 
 | |
| 		// macro stage 1...
 | |
| 		text = text.replace(this.__macro__pattern__, function(match, macro, args, text){
 | |
| 			args = that.parseArgs(args)
 | |
| 
 | |
| 			return macro in that.macro ? 
 | |
| 					that.macro[macro].call(that, args, text, filters)
 | |
| 				: match
 | |
| 		})
 | |
| 
 | |
| 		// macro stage 2...
 | |
| 		text = text.replace(this.__macro__pattern__, function(match, macro, args, text){
 | |
| 			args = that.parseArgs(args)
 | |
| 
 | |
| 			return macro in that.macro ? 
 | |
| 					that.macro[macro].call(that, args, text, filters)
 | |
| 				: match
 | |
| 		})
 | |
| 
 | |
| 		// filter stage....
 | |
| 		filters.forEach(function(k){
 | |
| 			text = that.filter[k].call(that, text) 
 | |
| 		})
 | |
| 
 | |
| 		return text
 | |
| 	},
 | |
| }
 | |
| 
 | |
| 
 | |
| 
 | |
| var reload = () => {
 | |
| 	$('.path').text('/' + Wiki.path)
 | |
| 
 | |
| 	$('.title').text(Wiki.title)
 | |
| 
 | |
| 	// process text...
 | |
| 	var text = Wiki.text
 | |
| 	var editing = $('.text').prop('contenteditable') != 'true'
 | |
| 	var filters = []
 | |
| 	var slots = {}
 | |
| 
 | |
| 	// expand macros...
 | |
| 	if(editing){
 | |
| 		text = text
 | |
| 			// Syntax:
 | |
| 			//		@<macro>( <args> )
 | |
| 			.replace(/@([a-zA-Z-_]+)\(([^)]*)\)/g, function(_, macro, args){
 | |
| 				args = $('<div>')
 | |
| 					.html(args)
 | |
| 					.text()
 | |
| 						.trim()
 | |
| 						.split(/\s+/g)
 | |
| 
 | |
| 				//console.log('>>>>>', macro, args)
 | |
| 
 | |
| 				if(macro == 'filter' && args.length == 1){
 | |
| 					filters.push(args[0])
 | |
| 					return ''
 | |
| 				}
 | |
| 
 | |
| 				if(macro == 'include' && args.length == 1){
 | |
| 					w = Object.create(Wiki)
 | |
| 					w.location = args[0]
 | |
| 					return w.text
 | |
| 				}
 | |
| 
 | |
| 				if(macro == 'attr' 
 | |
| 						&& args.length == 1
 | |
| 						&& ['title', 'path', 'location', 'dir'].indexOf(args[0]) >= 0){
 | |
| 					return Wiki[args[0]]
 | |
| 				}
 | |
| 
 | |
| 				return _
 | |
| 			})
 | |
| 			// html-like macro syntax...
 | |
| 			.replace(/\<[a-zA-Z-_:]+.*?\/?\>/g, function(t){
 | |
| 				var elem = $($('<div>').html(t).text())
 | |
| 				var macro = elem.prop('tagName').toLowerCase()
 | |
| 
 | |
| 				var args = {}
 | |
| 				var a = elem.prop('attributes')
 | |
| 
 | |
| 				for(var i=0; i<a.length; i++){
 | |
| 					args[a[i].name] = a[i].value
 | |
| 				}
 | |
| 
 | |
| 				//console.log('>>>>>', macro, args) 
 | |
| 
 | |
| 				if(macro == 'filter' && args.name != null){
 | |
| 					console.log('FILTER:', args.name)
 | |
| 					// XXX
 | |
| 					return ''
 | |
| 				}
 | |
| 
 | |
| 				if(macro == 'include' && args.src != null){
 | |
| 					w = Object.create(Wiki)
 | |
| 					w.location = args.src
 | |
| 					return w.text
 | |
| 				}
 | |
| 
 | |
| 				// XXX need content...
 | |
| 				// 		Procedure:
 | |
| 				//			- if new slot
 | |
| 				//				- add to list
 | |
| 				//				- fill
 | |
| 				//			- if slot exists
 | |
| 				//				- fill original
 | |
| 				if(macro == 'slot' && args.name != null){
 | |
| 					slots[args.name] = ''
 | |
| 					return t
 | |
| 				}
 | |
| 
 | |
| 				if(macro == 'attr' 
 | |
| 						&& args.name != null
 | |
| 						&& ['title', 'path', 'location', 'dir'].indexOf(args.name) >= 0){
 | |
| 					return Wiki[args.name]
 | |
| 				}
 | |
| 
 | |
| 				return t
 | |
| 			})
 | |
| 	}
 | |
| 
 | |
| 	$('.text').html(activateWikiWords(text, filters.indexOf('show_link_brackets') < 0 && editing))
 | |
| 
 | |
| 	// XXX save...
 | |
| 	localStorage['wiki-data'] = JSON.stringify(Wiki.__wiki_data)
 | |
| 	localStorage['wiki-location'] = Wiki.location
 | |
| 
 | |
| 	$('title').text(Wiki.location)
 | |
| }
 | |
| 
 | |
| var go = (path) => {
 | |
| 	history.pushState({
 | |
| 			wikipath: path
 | |
| 		}, 
 | |
| 		Wiki.title, 
 | |
| 		window.location)
 | |
| 
 | |
| 	Wiki.location = path
 | |
| 	reload()
 | |
| }
 | |
| 
 | |
| var clearWikiWords = elem => {
 | |
| 	// clear existing...
 | |
| 	elem.find('.WikiWord').each(function(){
 | |
| 		$(this).attr('braced') == 'yes' ? 
 | |
| 			$(this).replaceWith(['['].concat(this.childNodes, [']']))
 | |
| 			: $(this).replaceWith(this.childNodes)
 | |
| 	})
 | |
| 	return elem
 | |
| } 
 | |
| 
 | |
| var activateWikiWords = (text, show_brackets) => 
 | |
| 	text
 | |
| 		// set new...
 | |
| 		.replace(
 | |
| 			Wiki.__wiki_link__,
 | |
| 			function(l){
 | |
| 				return '<a '
 | |
| 					+'class="WikiWord" '
 | |
| 					+'href="#" '
 | |
| 					+'braced="'+ (show_brackets && l[0] == '[' ? 'yes' : 'no') +'"'
 | |
| 					+'onclick="go($(this).text().replace(/^\\[|\\]$/g, \'\'))">'
 | |
| 						+ (show_brackets && l[0] == '[' ? l.slice(1, -1) : l) 
 | |
| 					+'</a>'
 | |
| 			})
 | |
| 
 | |
| 
 | |
| $(() => {
 | |
| 	$(window).on('popstate', function(evt){
 | |
| 		event.state 
 | |
| 			&& event.state.wikipath 
 | |
| 			&& go(event.state.wikipath)
 | |
| 	})
 | |
| 
 | |
| 	// load stored data...
 | |
| 	Wiki.__wiki_data = localStorage['wiki-data'] ?
 | |
| 		JSON.parse(localStorage['wiki-data']) 
 | |
| 		: data
 | |
| 	Wiki.__wiki_data.__proto__ = BaseData
 | |
| 
 | |
| 	Wiki.location = localStorage['wiki-location'] || Wiki.location
 | |
| 
 | |
| 
 | |
| 	reload()
 | |
| 
 | |
| 	// XXX make this update on enter...
 | |
| 	$('.title')
 | |
| 		.on('blur', () => { 
 | |
| 			Wiki.title = $('.title').text() 
 | |
| 			reload()
 | |
| 		})
 | |
| 
 | |
| 	// live update text...
 | |
| 	// XXX is this the right way to go for large documents???
 | |
| 	$('.text')
 | |
| 		.focus(() => {
 | |
| 			$('.text').prop('contenteditable', $('.text').prop('contenteditable') != 'true')
 | |
| 			reload()
 | |
| 		})
 | |
| 		.on('keyup', () => { 
 | |
| 			if($('.text').prop('contenteditable') == 'true'){
 | |
| 				Wiki.text = clearWikiWords($('.text').clone()).html() 
 | |
| 			}
 | |
| 		})
 | |
| 		// XXX do this live, but on a timeout after user input...
 | |
| 		// XXX need to place the cursor in the same position...
 | |
| 		.blur(() => { 
 | |
| 			$('.text').prop('contenteditable', false)
 | |
| 			reload() 
 | |
| 		})
 | |
| })
 | |
| </script>
 | |
| 
 | |
| <body>
 | |
| 
 | |
| <div class="path"></div>
 | |
| <hr>
 | |
| <h1 class="title" contenteditable tabindex=0></h1>
 | |
| <div class="text" tabindex=0></div>
 | |
| 
 | |
| </body>
 | |
| </html>
 | |
| <!-- vim:set sw=4 ts=4 : -->
 |