mirror of
https://github.com/flynx/pWiki.git
synced 2025-12-25 20:31:58 +00:00
Compare commits
No commits in common. "d21d233b07c3199d394aa9f398193cc4e1b947d5" and "a3e5e4e3260126edb132892030cdc1789dba8f60" have entirely different histories.
d21d233b07
...
a3e5e4e326
@ -47,39 +47,16 @@
|
|||||||
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... */
|
||||||
@ -92,6 +69,21 @@
|
|||||||
.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;
|
||||||
@ -101,8 +93,7 @@
|
|||||||
.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 {
|
||||||
@ -264,25 +255,6 @@ 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.querySelector('.view').offsetParent != null })
|
return e.offsetParent != null })
|
||||||
: offset == 'viewport' ?
|
: offset == 'viewport' ?
|
||||||
[...node.querySelectorAll('.block')]
|
[...node.querySelectorAll('.block')]
|
||||||
.filter(function(e){
|
.filter(function(e){
|
||||||
return e.querySelector('.view').offsetParent != null
|
return e.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.querySelector('.view').offsetParent != null })
|
return e.offsetParent != null })
|
||||||
: offset == 'children' ?
|
: offset == 'children' ?
|
||||||
children(node)
|
children(node)
|
||||||
: offset == 'siblings' ?
|
: offset == 'siblings' ?
|
||||||
@ -1145,35 +1145,70 @@ 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 },
|
||||||
uncrop: function(mode=1){
|
// XXX use JSON API...
|
||||||
var outline = this.outline
|
uncrop: function(mode=undefined){
|
||||||
var top = this.get(0)
|
if(this.__crop_stack == null){
|
||||||
for(var block of [...this.outline.querySelectorAll('[cropped]')]){
|
return this }
|
||||||
block.removeAttribute('cropped') }
|
// XXX is this a good way do go???
|
||||||
// crop parent if available...
|
if(mode == 'all'){
|
||||||
while(mode != 'all'
|
while(this.__crop_stack != null){
|
||||||
&& mode > 0
|
this.uncrop() }
|
||||||
&& top !== outline){
|
return this }
|
||||||
top = this.get(top, 'parent')
|
|
||||||
mode-- }
|
// merge changes into the state above...
|
||||||
if(mode == 'all' || top === outline){
|
var stack = this.__crop_stack
|
||||||
this.dom.classList.remove('crop')
|
var [state, path, text] = stack
|
||||||
this.header.innerHTML = ''
|
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 {
|
} else {
|
||||||
this.crop(top) }
|
this.load(state)
|
||||||
|
this.dom.classList.remove('crop')
|
||||||
|
this.__crop_stack = undefined
|
||||||
|
this.header.innerHTML = '' }
|
||||||
|
|
||||||
return this },
|
return this },
|
||||||
|
|
||||||
// block render...
|
// block render...
|
||||||
@ -1329,7 +1364,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()
|
||||||
@ -1399,8 +1434,6 @@ 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()
|
||||||
@ -1424,10 +1457,10 @@ var Outline = {
|
|||||||
: place
|
: place
|
||||||
;(place == 'next'
|
;(place == 'next'
|
||||||
&& (cur.querySelector('.block')
|
&& (cur.querySelector('.block')
|
||||||
|| cur !== this.get(-1))) ?
|
|| cur.nextElementSibling)) ?
|
||||||
this.get(place).before(block)
|
this.get(place).before(block)
|
||||||
: (place == 'next'
|
: (place == 'next'
|
||||||
&& cur === this.get(-1)) ?
|
&& !cur.nextElementSibling) ?
|
||||||
cur.after(block)
|
cur.after(block)
|
||||||
: (place == 'before' || place == 'after') ?
|
: (place == 'before' || place == 'after') ?
|
||||||
cur[place](block)
|
cur[place](block)
|
||||||
|
|||||||
@ -51,6 +51,8 @@ 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, ...)
|
||||||
@ -111,9 +113,6 @@ 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:
|
||||||
@ -173,9 +172,6 @@ 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