mirror of
				https://github.com/flynx/pWiki.git
				synced 2025-10-31 19:10:08 +00:00 
			
		
		
		
	
		
			
				
	
	
		
			319 lines
		
	
	
		
			7.4 KiB
		
	
	
	
		
			HTML
		
	
	
		
			Executable File
		
	
	
	
	
			
		
		
	
	
			319 lines
		
	
	
		
			7.4 KiB
		
	
	
	
		
			HTML
		
	
	
		
			Executable File
		
	
	
	
	
| <!DOCTYPE html>
 | |
| <html>
 | |
| <!--html manifest="pwiki.appcache"-->
 | |
| <head>
 | |
| <title>pWiki</title>
 | |
| 
 | |
| <meta charset="utf-8">
 | |
| <meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=no">
 | |
| 
 | |
| <link rel="manifest" href="manifest.json">
 | |
| 
 | |
| <link rel="prefetch" href="css/fonts/Open_Sans/OpenSans-Bold.ttf">
 | |
| <link rel="prefetch" href="css/fonts/Open_Sans/OpenSans-BoldItalic.ttf">
 | |
| <link rel="prefetch" href="css/fonts/Open_Sans/OpenSans-ExtraBold.ttf">
 | |
| <link rel="prefetch" href="css/fonts/Open_Sans/OpenSans-ExtraBoldItalic.ttf">
 | |
| <link rel="prefetch" href="css/fonts/Open_Sans/OpenSans-Italic.ttf">
 | |
| <link rel="prefetch" href="css/fonts/Open_Sans/OpenSans-Light.ttf">
 | |
| <link rel="prefetch" href="css/fonts/Open_Sans/OpenSans-LightItalic.ttf">
 | |
| <link rel="prefetch" href="css/fonts/Open_Sans/OpenSans-Regular.ttf">
 | |
| <link rel="prefetch" href="css/fonts/Open_Sans/OpenSans-Semibold.ttf">
 | |
| <link rel="prefetch" href="css/fonts/Open_Sans/OpenSans-SemiboldItalic.ttf">
 | |
| 
 | |
| <link rel="stylesheet" href="css/fonts.css">
 | |
| 
 | |
| </head>
 | |
| 
 | |
| <style>
 | |
| 
 | |
| body {
 | |
| 	font-size: 1.1em;
 | |
| }
 | |
| 
 | |
| a {
 | |
| 	text-decoration: none;
 | |
| }
 | |
| a:hover {
 | |
| 	text-decoration: underline;
 | |
| }
 | |
| 
 | |
| .show-on-hover {
 | |
| 	opacity: 0;
 | |
| }
 | |
| :hover>.show-on-hover {
 | |
| 	opacity: 0.4;
 | |
| }
 | |
| .show-on-hover:hover {
 | |
| 	opacity: 0.8;
 | |
| }
 | |
| 
 | |
| /* Spinner... */
 | |
| .spinner {
 | |
| 	position: absolute;
 | |
| 	display: flex;
 | |
| 	text-align: center;
 | |
| 	left: 50%;
 | |
| 	top: 50%;
 | |
| 	width: 100px;
 | |
| 	height: 100px;
 | |
| 	margin-top: -50px;
 | |
| 	margin-left: -50px;
 | |
| 	white-space: nowrap;
 | |
| 
 | |
| 	background: transparent;
 | |
| 	pointer-events: none;
 | |
| 
 | |
| 	animation: fadein 2s 1;
 | |
| }
 | |
| .spinner span {
 | |
| 	position: relative;
 | |
| 	display: inline-block;
 | |
| 	font-size: 2em;
 | |
| 
 | |
| 	animation: loading 2s infinite ;
 | |
| 	animation-delay: calc(0.2s * var(--i));
 | |
| }
 | |
| body:not(.loading) .page.spinner {
 | |
| 	display: none;
 | |
| }
 | |
| body.loading .page.spinner {
 | |
| 	opacity: 0.9;
 | |
| 	animation: fadein 1s 1;
 | |
| }
 | |
| body.loading .page.spinner span {
 | |
| 	font-size: 4em;
 | |
| 	animation: loading 2s infinite ;
 | |
| 	animation-delay: calc(0.2s * var(--i));
 | |
| }
 | |
| @keyframes fadein {
 | |
| 	from {
 | |
| 		opacity: 0;
 | |
| 	}
 | |
| 	50% {
 | |
| 		opacity: 0.8;
 | |
| 	}
 | |
| 	to {
 | |
| 		opacity: 1;
 | |
| 	}
 | |
| }
 | |
| @keyframes loading {
 | |
| 	0%, 60% {
 | |
| 		transform: rotateY(360deg);
 | |
| 	}
 | |
| }
 | |
| 
 | |
| 
 | |
| </style>
 | |
| 
 | |
| <!-- XXX do we need this??? -->
 | |
| <script src="bootstrap.js"></script>
 | |
| 
 | |
| <!--script data-main="pwiki2" src="ext-lib/require.js"></script-->
 | |
| <script src="ext-lib/require.js"></script>
 | |
| <script>
 | |
| 
 | |
| var DEBUG = true
 | |
| 
 | |
| 
 | |
| var makeFallbacks = 
 | |
| function(paths, search=['lib']){
 | |
| 	return Object.entries(paths)
 | |
| 		.map(function([key, path]){
 | |
| 			// package...
 | |
| 			if(path.endsWith('/')){
 | |
| 				return [key, path] }
 | |
| 			return [
 | |
| 				key,
 | |
| 				[
 | |
| 					path,
 | |
| 					...search
 | |
| 						.map(function(base){
 | |
| 							return base +'/'+ path.split(/[\\\/]+/g).pop() }),
 | |
| 				]
 | |
| 			] })
 | |
| 		.reduce(function(res, [key, value]){
 | |
| 			res[key] = value
 | |
| 			return res }, {}) }
 | |
| 
 | |
| 
 | |
| require.config({
 | |
| 	paths: {
 | |
| 		...makeFallbacks({
 | |
| 			'ig-doc': 'node_modules/ig-doc/doc',
 | |
| 			'ig-stoppable': 'node_modules/ig-stoppable/stoppable',
 | |
| 			'object-run': 'node_modules/object-run/run',
 | |
| 			'ig-object': 'node_modules/ig-object/object',
 | |
| 		}),
 | |
| 
 | |
| 		// packages...
 | |
| 		'ig-types': [
 | |
| 			'node_modules/ig-types',
 | |
| 			'lib/types',
 | |
| 		],
 | |
| 
 | |
| 		// external stuff...
 | |
| 		...makeFallbacks({
 | |
| 			'jszip': 'node_modules/jszip/dist/jszip',
 | |
| 			'pouchdb': 'node_modules/pouchdb/dist/pouchdb',
 | |
| 			'showdown': 'node_modules/showdown/dist/showdown',
 | |
| 		}, ['ext-lib']),
 | |
| 	},
 | |
| 	packages: [
 | |
| 		'ig-types',
 | |
| 	]
 | |
| })
 | |
| 
 | |
| 
 | |
| document.pwikiloaded = new Event('pwikiloaded')
 | |
| 
 | |
| REFRESH_DELAY = 20
 | |
| 
 | |
| // helper...
 | |
| var logTime = async function(promise, msg=''){
 | |
| 	var t = Date.now()
 | |
| 	var res = await promise
 | |
| 	t = Date.now() - t
 | |
| 	DEBUG 
 | |
| 		&& console.log(`## ${
 | |
| 				typeof(msg) == 'function' ? 
 | |
| 					msg(res) 
 | |
| 					: msg
 | |
| 			} (${t}ms)`)
 | |
| 	return res }
 | |
| 
 | |
| // start loading pWiki...
 | |
| require(['./browser'], function(browser){ 
 | |
| 	pwiki = window.pwiki = browser.pwiki 
 | |
| 	pwiki.dom = document.querySelector('#pWiki')
 | |
| 
 | |
| 	// handle location.hash/history (both directions)
 | |
| 	window.addEventListener('hashchange', function(evt){
 | |
| 		evt.preventDefault()
 | |
| 		var [path, hash] = decodeURI(location.hash).slice(1).split('#')
 | |
| 		path = path.trim() == '' ? 
 | |
| 			pwiki.location
 | |
| 			//'/'
 | |
| 			: path
 | |
| 		// treat links as absolute unless explicitly relative...
 | |
| 		path = /^\.\.?([\\\/].*)?$/.test(path) ?
 | |
| 			path
 | |
| 			: '/'+path
 | |
| 		startSpinner()
 | |
| 		// NOTE: setTimeout(..) to allow the spinner to start...
 | |
| 		// NOTE: this seems not to work if the REFRESH_DELAY is too small...
 | |
| 		setTimeout(function(){
 | |
| 			pwiki.location = [path, hash] }, REFRESH_DELAY) })
 | |
| 	pwiki
 | |
| 		.onBeforeNavigate(function(){
 | |
| 			saveNow() })
 | |
| 		.onNavigate(async function(){
 | |
| 			// NOTE: we do not need to directly update location.hash here as
 | |
| 			//		that will push an extra history item...
 | |
| 			history.replaceState(
 | |
| 				{path: this.location}, 
 | |
| 				'',
 | |
| 				'#'+this.location 
 | |
| 					+(this.hash ? 
 | |
| 						'#'+this.hash 
 | |
| 						: ''))
 | |
| 			// NOTE: we are intentionally not awaiting for this -- this 
 | |
| 			//		separates the navigate and load events...
 | |
| 			logTime(
 | |
| 				this.refresh(), 
 | |
| 				this.location) })
 | |
| 		.onLoad(function(evt){
 | |
| 			var that = this
 | |
| 			// stop spinner...
 | |
| 			stopSpinner()
 | |
| 			// handle title...
 | |
| 			document.querySelector('title').innerHTML = this.path
 | |
| 			// scroll to anchor element...
 | |
| 			this.hash
 | |
| 				&& this.dom
 | |
| 					.querySelector('#'+ this.hash)
 | |
| 					.scrollIntoView() 
 | |
| 			// handle refresh...
 | |
| 			// NOTE: we need to do this as hashchange is only triggered 
 | |
| 			//		when the hash is actually changed...
 | |
| 			for(var lnk of this.dom.querySelectorAll(`a[href="${location.hash}"]`)){
 | |
| 				lnk.addEventListener('click', function(evt){
 | |
| 					startSpinner()
 | |
| 					setTimeout(function(){
 | |
| 						logTime(
 | |
| 							that.refresh(), 
 | |
| 							that.location) }, REFRESH_DELAY) }) } })
 | |
| 
 | |
| 	// wait for stuff to finish...
 | |
| 	browser.setup.then(function(){
 | |
| 		// show current page...
 | |
| 		pwiki.location = decodeURI(location.hash).slice(1) }) }) 
 | |
| 
 | |
| 
 | |
| // XXX versioning??
 | |
| var SAVE_TIMEOUT = 5000
 | |
| var SAVE_QUEUE = {}
 | |
| var saveContent = 
 | |
| 	function(path, text){
 | |
| 		SAVE_QUEUE[path] = text 
 | |
| 		// clear editor page cache...
 | |
| 		pwiki.cache = null }
 | |
| var saveNow = 
 | |
| 	function(){
 | |
| 		var queue = Object.entries(SAVE_QUEUE)
 | |
| 		SAVE_QUEUE = {}
 | |
| 		queue
 | |
| 			.forEach(function([path, text]){
 | |
| 				console.log('saving changes to:', path)
 | |
| 				pwiki.get(path).raw = text }) }
 | |
| setInterval(saveNow, 5000)
 | |
| 
 | |
| // loading spinner...
 | |
| window.startSpinner = function(){
 | |
| 	document.body.classList.add('loading') }
 | |
| window.stopSpinner = function(){
 | |
| 	document.body.classList.remove('loading') }
 | |
| 
 | |
| 
 | |
| // XXX
 | |
| var exportData = async function(){
 | |
| 	var blob = new Blob([await pwiki.store.json(true)], {type: "text/plain;charset=utf-8"});
 | |
| 
 | |
| 	var a = document.createElement('a')
 | |
|     var blobURL = a.href = URL.createObjectURL(blob)
 | |
|     a.download = 'pWiki-dump.json'
 | |
| 
 | |
|     //document.body.appendChild(a)
 | |
|     a.dispatchEvent(new MouseEvent("click"))
 | |
|     //document.body.removeChild(a)
 | |
|     //URL.revokeObjectURL(blobURL)
 | |
| }
 | |
| 
 | |
| 
 | |
| 
 | |
| 
 | |
| </script>
 | |
| 
 | |
| <body>
 | |
| 
 | |
| <!-- XXX need to add something passive but animated here... -->
 | |
| <div id="pWiki">
 | |
| 	<div class="spinner">
 | |
| 		<span style="--i:0">p</span>
 | |
| 		<span style="--i:1">W</span>
 | |
| 		<span style="--i:2">i</span>
 | |
| 		<span style="--i:3">k</span>
 | |
| 		<span style="--i:4">i</span>
 | |
| 	</div>
 | |
| </div>
 | |
| 
 | |
| <div class="page spinner">
 | |
| 	<span style="--i:0">.</span>
 | |
| 	<span style="--i:1">.</span>
 | |
| 	<span style="--i:2">.</span>
 | |
| </div>
 | |
| 
 | |
| </body>
 | |
| </html>
 | |
| 
 | |
| <!-- vim:set sw=4 ts=4 : -->
 |