pWiki/pwiki2.html

379 lines
8.9 KiB
HTML
Raw Normal View History

<!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);
}
}
[contenteditable] {
outline: 0px solid transparent;
}
[contenteditable]:empty:after {
display: block;
content: 'Empty';
opacity: 0.3;
}
</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
//---------------------------------------------------------------------
// Module loading...
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',
]
})
//---------------------------------------------------------------------
// Editor -- save changes...
// XXX versioning??
var SAVE_LIVE_TIMEOUT = 5000
var SAVE_LIVE_QUEUE = {}
var saveLiveContent =
function(path, text){
SAVE_LIVE_QUEUE[path] = text
// clear editor page cache...
pwiki.cache = null }
var SAVE_QUEUE = {}
var saveContent =
function(path, text){
SAVE_QUEUE[path] = text }
var saveAll =
function(){
saveNow()
var queue = Object.entries(SAVE_QUEUE)
SAVE_QUEUE = {}
queue
.forEach(function([path, text]){
console.log('saving changes to:', path)
pwiki.get(path).raw = text }) }
var saveNow =
function(){
var queue = Object.entries(SAVE_LIVE_QUEUE)
SAVE_LIVE_QUEUE = {}
NEW_TITLE = undefined
queue
.forEach(function([path, text]){
console.log('saving changes to:', path)
pwiki.get(path).raw = text }) }
setInterval(saveNow, SAVE_LIVE_TIMEOUT)
//---------------------------------------------------------------------
// Spinner/loading...
// loading spinner...
window.startSpinner = function(){
document.body.classList.add('loading') }
window.stopSpinner = function(){
document.body.classList.remove('loading') }
//---------------------------------------------------------------------
// General setup...
document.pwikiloaded = new Event('pwikiloaded')
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 }
REFRESH_DELAY = 20
var refresh = async function(){
startSpinner()
setTimeout(function(){
logTime(
pwiki.refresh(),
pwiki.location) }, REFRESH_DELAY) }
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// start loading pWiki...
require(['./browser'], function(browser){
var 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(){
saveAll() })
.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.title} &mdash; pWiki`
// 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', refresh) } })
// wait for stuff to finish...
browser.setup.then(function(){
// show current page...
pwiki.location = decodeURI(location.hash).slice(1) }) })
//---------------------------------------------------------------------
// Export...
// XXX
var exportData = async function(options={}){
var filename
if(typeof(options) == 'string'){
filename = options
options = arguments[1] ?? {} }
var blob = new Blob(
[await pwiki.store.json({stringify: true, space: 4, ...options})],
{type: "text/plain;charset=utf-8"});
var a = document.createElement('a')
var blobURL = a.href = URL.createObjectURL(blob)
a.download = filename
?? options.filename
?? (Date.timeStamp() +'.pWiki.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 : -->