mirror of
https://github.com/flynx/pWiki.git
synced 2025-12-25 20:31:58 +00:00
Compare commits
6 Commits
a3e5e4e326
...
d21d233b07
| Author | SHA1 | Date | |
|---|---|---|---|
| d21d233b07 | |||
| b80312497c | |||
| f07a4e5b66 | |||
| bf8ac4e089 | |||
| e2092e808d | |||
| 2bd9781951 |
@ -47,16 +47,39 @@
|
|||||||
display: none;
|
display: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
.editor .children {
|
|
||||||
|
/* header */
|
||||||
|
.editor .header {
|
||||||
|
margin: 1em var(--outline-padding);
|
||||||
|
padding-bottom: 1.2em;
|
||||||
|
|
||||||
|
border-bottom: solid 1px rgba(0,0,0,0.15);
|
||||||
|
}
|
||||||
|
.editor .header:empty {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
.editor .header .path-item {
|
||||||
|
color: gray;
|
||||||
|
cursor: pointer;
|
||||||
|
/* XXX needs more work... */
|
||||||
|
max-width: 10rem;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
}
|
||||||
|
.editor .header .path-item:hover {
|
||||||
|
text-decoration: underline;
|
||||||
|
}
|
||||||
|
.editor .header .path-item:first-child {
|
||||||
|
padding-left: 3em;
|
||||||
|
margin-left: -2em;
|
||||||
}
|
}
|
||||||
|
|
||||||
.editor .header,
|
|
||||||
.editor .outline {
|
.editor .outline {
|
||||||
display: block;
|
display: block;
|
||||||
position: relative;
|
position: relative;
|
||||||
|
|
||||||
padding: 1em var(--outline-padding);
|
padding: 1em var(--outline-padding);
|
||||||
padding-bottom: 1.2em
|
padding-bottom: 1.2em;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* virtual empty block... */
|
/* virtual empty block... */
|
||||||
@ -69,21 +92,6 @@
|
|||||||
.editor .outline:empty:hover:after {
|
.editor .outline:empty:hover:after {
|
||||||
}
|
}
|
||||||
|
|
||||||
/* XXX header */
|
|
||||||
.editor .header {
|
|
||||||
}
|
|
||||||
.editor .header:empty {
|
|
||||||
display: none;
|
|
||||||
}
|
|
||||||
/* XXX needs more work... *//*
|
|
||||||
.editor .header span {
|
|
||||||
display: inline;
|
|
||||||
max-width: 10rem;
|
|
||||||
text-overflow: ellipsis;
|
|
||||||
overflow: hidden;
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
.editor .outline .block {
|
.editor .outline .block {
|
||||||
position: relative;
|
position: relative;
|
||||||
@ -93,7 +101,8 @@
|
|||||||
.editor.block-offsets .outline .block {
|
.editor.block-offsets .outline .block {
|
||||||
border-left: solid 1px silver;
|
border-left: solid 1px silver;
|
||||||
}
|
}
|
||||||
.editor .outline .block .block {
|
.editor .outline .block .block,
|
||||||
|
.editor.crop .outline .block[cropped] .block[cropped] {
|
||||||
margin-left: var(--item-indent);
|
margin-left: var(--item-indent);
|
||||||
}
|
}
|
||||||
.editor .outline .block>.text {
|
.editor .outline .block>.text {
|
||||||
@ -255,6 +264,25 @@ editor .outline .block:focus {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* crop... */
|
||||||
|
/* NOTE: also see rules for: .editor .outline .block .block
|
||||||
|
* ...can we avoid this?? (XXX) */
|
||||||
|
.editor.crop .outline .block:not([cropped]) {
|
||||||
|
padding: 0;
|
||||||
|
border: none;
|
||||||
|
background: none;
|
||||||
|
}
|
||||||
|
.editor.crop .outline .block:not([cropped])>.text {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
.editor.crop .outline .block[cropped] {
|
||||||
|
margin-left: 0;
|
||||||
|
}
|
||||||
|
.editor.crop .outline .block[cropped] .text {
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
.editor .toolbar {
|
.editor .toolbar {
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
position: absolute;
|
position: absolute;
|
||||||
|
|||||||
@ -895,18 +895,18 @@ var Outline = {
|
|||||||
: offset == 'visible' ?
|
: offset == 'visible' ?
|
||||||
[...node.querySelectorAll('.block')]
|
[...node.querySelectorAll('.block')]
|
||||||
.filter(function(e){
|
.filter(function(e){
|
||||||
return e.offsetParent != null })
|
return e.querySelector('.view').offsetParent != null })
|
||||||
: offset == 'viewport' ?
|
: offset == 'viewport' ?
|
||||||
[...node.querySelectorAll('.block')]
|
[...node.querySelectorAll('.block')]
|
||||||
.filter(function(e){
|
.filter(function(e){
|
||||||
return e.offsetParent != null
|
return e.querySelector('.view').offsetParent != null
|
||||||
&& e.querySelector('.code').visibleInViewport() })
|
&& e.querySelector('.code').visibleInViewport() })
|
||||||
: offset == 'editable' ?
|
: offset == 'editable' ?
|
||||||
[...node.querySelectorAll('.block>.code')]
|
[...node.querySelectorAll('.block>.code')]
|
||||||
: offset == 'selected' ?
|
: offset == 'selected' ?
|
||||||
[...node.querySelectorAll('.block[selected]')]
|
[...node.querySelectorAll('.block[selected]')]
|
||||||
.filter(function(e){
|
.filter(function(e){
|
||||||
return e.offsetParent != null })
|
return e.querySelector('.view').offsetParent != null })
|
||||||
: offset == 'children' ?
|
: offset == 'children' ?
|
||||||
children(node)
|
children(node)
|
||||||
: offset == 'siblings' ?
|
: offset == 'siblings' ?
|
||||||
@ -1145,70 +1145,35 @@ var Outline = {
|
|||||||
return this },
|
return this },
|
||||||
|
|
||||||
// crop...
|
// crop...
|
||||||
// XXX shoud we control crops as "crop in" / "crop out" instead of crom/uncrop???
|
|
||||||
// XXX add crop-level/path indicator...
|
|
||||||
__crop_stack: undefined,
|
|
||||||
crop: function(node='focused'){
|
crop: function(node='focused'){
|
||||||
var that = this
|
|
||||||
|
|
||||||
var stack = this.__crop_stack =
|
|
||||||
this.__crop_stack ?? []
|
|
||||||
var state = stack[0] = stack[0] ?? this.json()
|
|
||||||
var path = stack[1] = stack[1] ?
|
|
||||||
[...stack[1], ...this.path().slice(1)]
|
|
||||||
: this.path(...arguments)
|
|
||||||
stack[2] = [
|
|
||||||
...(stack[2] ?? []),
|
|
||||||
...this.path('text').slice(0, -1),
|
|
||||||
]
|
|
||||||
// clear focused -- prevent focus from shifting on uncrop...
|
|
||||||
var e = state
|
|
||||||
for(var i of path.slice(0, -1)){
|
|
||||||
e = e[i].children }
|
|
||||||
delete e[path.at(-1)].focused
|
|
||||||
|
|
||||||
|
|
||||||
this.load(this.data(...arguments))
|
|
||||||
|
|
||||||
// XXX make this linkable...
|
|
||||||
this.header.innerHTML = '/ ' + stack[2].join(' / ')
|
|
||||||
this.dom.classList.add('crop')
|
this.dom.classList.add('crop')
|
||||||
|
for(var block of [...this.outline.querySelectorAll('[cropped]')]){
|
||||||
|
block.removeAttribute('cropped') }
|
||||||
|
this.get(...arguments).setAttribute('cropped', '')
|
||||||
|
this.header.innerHTML =
|
||||||
|
`<span class="path-item" onclick="editor.uncrop('all')">/</span> `
|
||||||
|
+ this.path(...arguments, 'text')
|
||||||
|
.slice(0, -1)
|
||||||
|
.map(function(s, i, {length}){
|
||||||
|
return `<span class="path-item" onclick="editor.uncrop(${ length-i })">${s}</span> ` })
|
||||||
|
.join(' / ')
|
||||||
return this },
|
return this },
|
||||||
// XXX use JSON API...
|
uncrop: function(mode=1){
|
||||||
uncrop: function(mode=undefined){
|
var outline = this.outline
|
||||||
if(this.__crop_stack == null){
|
var top = this.get(0)
|
||||||
return this }
|
for(var block of [...this.outline.querySelectorAll('[cropped]')]){
|
||||||
// XXX is this a good way do go???
|
block.removeAttribute('cropped') }
|
||||||
if(mode == 'all'){
|
// crop parent if available...
|
||||||
while(this.__crop_stack != null){
|
while(mode != 'all'
|
||||||
this.uncrop() }
|
&& mode > 0
|
||||||
return this }
|
&& top !== outline){
|
||||||
|
top = this.get(top, 'parent')
|
||||||
// merge changes into the state above...
|
mode-- }
|
||||||
var stack = this.__crop_stack
|
if(mode == 'all' || top === outline){
|
||||||
var [state, path, text] = stack
|
|
||||||
var s = state
|
|
||||||
for(var i of path.slice(0, -1)){
|
|
||||||
s = s[i].children }
|
|
||||||
s.splice(path.at(-1), 1, ...this.json())
|
|
||||||
|
|
||||||
if(path.length > 1){
|
|
||||||
path.pop()
|
|
||||||
text.pop()
|
|
||||||
s = state
|
|
||||||
for(var i of path.slice(0, -1)){
|
|
||||||
s = s[i].children }
|
|
||||||
s = s[path.at(-1)]
|
|
||||||
this.load(s)
|
|
||||||
this.header.innerHTML =
|
|
||||||
'/ ' + stack[2].join(' / ')
|
|
||||||
|
|
||||||
} else {
|
|
||||||
this.load(state)
|
|
||||||
this.dom.classList.remove('crop')
|
this.dom.classList.remove('crop')
|
||||||
this.__crop_stack = undefined
|
this.header.innerHTML = ''
|
||||||
this.header.innerHTML = '' }
|
} else {
|
||||||
|
this.crop(top) }
|
||||||
return this },
|
return this },
|
||||||
|
|
||||||
// block render...
|
// block render...
|
||||||
@ -1364,7 +1329,7 @@ var Outline = {
|
|||||||
// ...putting the same pattern in a normal group and
|
// ...putting the same pattern in a normal group and
|
||||||
// returning it works fine...
|
// returning it works fine...
|
||||||
//.replace(/(?<=[\n\h]*)(?:(?:\n|^)\s*\w*\s*::\s*[^\n]*\s*)*$/,
|
//.replace(/(?<=[\n\h]*)(?:(?:\n|^)\s*\w*\s*::\s*[^\n]*\s*)*$/,
|
||||||
.replace(/([\n\t ]*)(?:(?:\n|^)[\t ]*\w*[\t ]*::[\t ]*[^\n]*[\t ]*)+$/,
|
.replace(/([\n\t ]*)(?:(?:\n|^)[\t ]*\w+[\t ]*::[\t ]*[^\n]+[\t ]*)+$/,
|
||||||
function(match, ws){
|
function(match, ws){
|
||||||
var attrs = match
|
var attrs = match
|
||||||
.trim()
|
.trim()
|
||||||
@ -1434,6 +1399,8 @@ var Outline = {
|
|||||||
var block = document.createElement('div')
|
var block = document.createElement('div')
|
||||||
block.classList.add('block')
|
block.classList.add('block')
|
||||||
block.setAttribute('tabindex', '0')
|
block.setAttribute('tabindex', '0')
|
||||||
|
// XXX hack??
|
||||||
|
block.setAttribute('cropped', '')
|
||||||
// code...
|
// code...
|
||||||
var code = document.createElement('textarea')
|
var code = document.createElement('textarea')
|
||||||
.autoUpdateSize()
|
.autoUpdateSize()
|
||||||
@ -1457,10 +1424,10 @@ var Outline = {
|
|||||||
: place
|
: place
|
||||||
;(place == 'next'
|
;(place == 'next'
|
||||||
&& (cur.querySelector('.block')
|
&& (cur.querySelector('.block')
|
||||||
|| cur.nextElementSibling)) ?
|
|| cur !== this.get(-1))) ?
|
||||||
this.get(place).before(block)
|
this.get(place).before(block)
|
||||||
: (place == 'next'
|
: (place == 'next'
|
||||||
&& !cur.nextElementSibling) ?
|
&& cur === this.get(-1)) ?
|
||||||
cur.after(block)
|
cur.after(block)
|
||||||
: (place == 'before' || place == 'after') ?
|
: (place == 'before' || place == 'after') ?
|
||||||
cur[place](block)
|
cur[place](block)
|
||||||
|
|||||||
@ -51,8 +51,6 @@ var setup = function(){
|
|||||||
- BUG: mobile browsers behave quite chaotically ignoring parts of the styling...
|
- BUG: mobile browsers behave quite chaotically ignoring parts of the styling...
|
||||||
-
|
-
|
||||||
- ## ToDo:
|
- ## ToDo:
|
||||||
- Q: crop: should we control crop via "crop-in"/"crop-out" instead of crop/uncrop??
|
|
||||||
- crop: make path clickable
|
|
||||||
- undo
|
- undo
|
||||||
collapsed:: true
|
collapsed:: true
|
||||||
- edit stack (position, action, ...)
|
- edit stack (position, action, ...)
|
||||||
@ -113,6 +111,9 @@ var setup = function(){
|
|||||||
- empty item height is a bit off...
|
- empty item height is a bit off...
|
||||||
- search?
|
- search?
|
||||||
- _...not sure if search should be internal or external yet..._
|
- _...not sure if search should be internal or external yet..._
|
||||||
|
- DONE crop: make path clickable
|
||||||
|
- DONE Q: crop: should we control crop via "crop-in"/"crop-out" instead of crop/uncrop??
|
||||||
|
- _crop-in/crop-out seems more natural..._
|
||||||
- DONE crop: show crop path (and depth)
|
- DONE crop: show crop path (and depth)
|
||||||
- DONE over-travel pause -- when going fast over start/end stop...
|
- DONE over-travel pause -- when going fast over start/end stop...
|
||||||
- DONE focus:
|
- DONE focus:
|
||||||
@ -172,6 +173,9 @@ var setup = function(){
|
|||||||
- DONE add optional text styling to nodes
|
- DONE add optional text styling to nodes
|
||||||
-
|
-
|
||||||
- ## Refactoring:
|
- ## Refactoring:
|
||||||
|
- Q: Implementation: JSON-based, DOM-based (current) or both?
|
||||||
|
- implement JSON-based
|
||||||
|
- compare and decide...
|
||||||
- Plugin architecture
|
- Plugin architecture
|
||||||
- DONE basic structure
|
- DONE basic structure
|
||||||
- plugin handler sequencing (see: `<editor>.setup(..)`)
|
- plugin handler sequencing (see: `<editor>.setup(..)`)
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user