mirror of
https://github.com/flynx/pWiki.git
synced 2025-12-25 04:11:56 +00:00
Compare commits
5 Commits
6d25e096ce
...
475078b55c
| Author | SHA1 | Date | |
|---|---|---|---|
| 475078b55c | |||
| b8ba68c06b | |||
| 14fec24aaf | |||
| 273c14aa20 | |||
| 118bbbe640 |
@ -8,7 +8,6 @@
|
||||
|
||||
--item-indent: 2rem;
|
||||
--item-padding-ratio: 0.2;
|
||||
--item-padding: calc(1em * var(--item-padding-ratio));
|
||||
|
||||
--checkbox-size: 1.5rem;
|
||||
|
||||
@ -29,6 +28,14 @@
|
||||
/*scroll-behavior: smooth;*/
|
||||
}
|
||||
|
||||
.editor {
|
||||
--item-padding: calc(1em * var(--item-padding-ratio));
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*********************************************************************/
|
||||
|
||||
.editor {
|
||||
display: block;
|
||||
position: relative;
|
||||
@ -105,6 +112,11 @@
|
||||
overflow: hidden;
|
||||
resize: none;
|
||||
}
|
||||
/* clickable things in view */
|
||||
.editor .outline [tabindex]>span a,
|
||||
.editor .outline [tabindex]>span input {
|
||||
pointer-events: auto;
|
||||
}
|
||||
|
||||
|
||||
/* focus... */
|
||||
@ -118,7 +130,7 @@ editor .outline [tabindex]:focus {
|
||||
}
|
||||
.editor .outline [tabindex].focused:not(:focus)>span,
|
||||
.editor .outline [tabindex].focused:not(:focus)>textarea {
|
||||
background: rgba(0,0,0,0.05);
|
||||
background: rgba(0,0,0,0.01);
|
||||
}
|
||||
|
||||
.editor .outline div[collapsed] {
|
||||
@ -259,9 +271,28 @@ editor .outline [tabindex]:focus {
|
||||
}
|
||||
|
||||
|
||||
/* Quote... */
|
||||
.editor .outline .quote>span,
|
||||
.editor .outline .quote>textarea {
|
||||
--item-padding-ratio: 0.7;
|
||||
--indent: 1rem;
|
||||
|
||||
/* XXX for some reason if this is not set here it will not see the new --item-padding-ratio */
|
||||
--item-padding: calc(1rem * var(--item-padding-ratio));
|
||||
|
||||
padding: var(--item-padding) 1.5rem;
|
||||
color: rgba(0,0,0,0.8);
|
||||
|
||||
/* XXX border messes up bullet alignment... */
|
||||
/*border-left: solid 0.2em silver;*/
|
||||
box-shadow: inset 0.2em 0 0 0 silver;
|
||||
background: rgba(0,0,0,0.05);
|
||||
}
|
||||
|
||||
|
||||
/* Lists... */
|
||||
/* XXX needs to be in the middle of the first span but with universal size... */
|
||||
.editor .outline .list-item:before,
|
||||
.editor .outline .list-item>span:before,
|
||||
.editor .outline .list>[tabindex]>span:not(:empty):before {
|
||||
content: "◼";
|
||||
color: gray;
|
||||
@ -305,9 +336,6 @@ editor .outline [tabindex]:focus {
|
||||
* element -- can's seem to figure out a way to avoid this */
|
||||
--checkbox-margin: 0em;
|
||||
}
|
||||
.editor .outline input {
|
||||
pointer-events: auto;
|
||||
}
|
||||
.editor .outline [tabindex].todo>span {
|
||||
width: calc(100% - var(--checkbox-size));
|
||||
/* align todo checkboxes to indnt (otherwise they are on the indent) */
|
||||
@ -348,6 +376,13 @@ editor .outline [tabindex]:focus {
|
||||
/*margin-left: 0;*/
|
||||
}
|
||||
|
||||
/* code... */
|
||||
.editor .outline [tabindex]>span code {
|
||||
padding: 0.1em 0.3em;
|
||||
font-family: monospace;
|
||||
background: rgba(0,0,0,0.07);
|
||||
border-radius: 0.2em;
|
||||
}
|
||||
|
||||
|
||||
/*********************************************************************/
|
||||
@ -355,6 +390,7 @@ editor .outline [tabindex]:focus {
|
||||
.editor.show-click-zones .outline [tabindex]>span:before,
|
||||
.editor.show-click-zones .outline [tabindex]>span:after {
|
||||
background: rgba(0,0,0,0.03);
|
||||
border: solid 1px silver;
|
||||
}
|
||||
.editor.show-click-zones .outline [tabindex]:hover>span:before,
|
||||
.editor.show-click-zones .outline [tabindex]:hover>span:after {
|
||||
|
||||
@ -178,9 +178,9 @@ var Outline = {
|
||||
focus: function(node='focused', offset){},
|
||||
edit: function(node='focused', offset){},
|
||||
|
||||
// XXX should this handle children???
|
||||
update: function(node='focused', data){
|
||||
var node = this.get(node)
|
||||
data ??= this.data(node, false)
|
||||
typeof(data.collapsed) == 'boolean'
|
||||
&& (data.collapsed ?
|
||||
node.setAttribute('collapsed', '')
|
||||
@ -193,9 +193,9 @@ var Outline = {
|
||||
var parsed = this.__code2html__(data.text)
|
||||
html.innerHTML = parsed.text
|
||||
// heading...
|
||||
parsed.style ?
|
||||
node.classList.add(...parsed.style)
|
||||
: node.classList.remove(...this.__styles)
|
||||
node.classList.remove(...this.__styles)
|
||||
parsed.style
|
||||
&& node.classList.add(...parsed.style)
|
||||
} else {
|
||||
html.innerHTML = data.text }
|
||||
text.value = data.text
|
||||
@ -312,36 +312,66 @@ var Outline = {
|
||||
return '' })
|
||||
// markdown...
|
||||
// style: headings...
|
||||
.replace(/^######\s*(.*)$/m, style('heading-6'))
|
||||
.replace(/^#####\s*(.*)$/m, style('heading-5'))
|
||||
.replace(/^####\s*(.*)$/m, style('heading-4'))
|
||||
.replace(/^###\s*(.*)$/m, style('heading-3'))
|
||||
.replace(/^##\s*(.*)$/m, style('heading-2'))
|
||||
.replace(/^#\s*(.*)$/m, style('heading-1'))
|
||||
.replace(/^(?<!\\)######\s+(.*)$/m, style('heading-6'))
|
||||
.replace(/^(?<!\\)#####\s+(.*)$/m, style('heading-5'))
|
||||
.replace(/^(?<!\\)####\s+(.*)$/m, style('heading-4'))
|
||||
.replace(/^(?<!\\)###\s+(.*)$/m, style('heading-3'))
|
||||
.replace(/^(?<!\\)##\s+(.*)$/m, style('heading-2'))
|
||||
.replace(/^(?<!\\)#\s+(.*)$/m, style('heading-1'))
|
||||
// style: list...
|
||||
.replace(/^[-\*]\s+(.*)$/m, style('list-item'))
|
||||
.replace(/^\s*(.*):\s*$/m, style('list'))
|
||||
//.replace(/^(?<!\\)[-\*]\s+(.*)$/m, style('list-item'))
|
||||
.replace(/^\s*(.*)(?<!\\):\s*$/m, style('list'))
|
||||
// style: misc...
|
||||
.replace(/^((\/\/|;)\s+.*)$/m, style('comment'))
|
||||
.replace(/^XXX\s+(.*)$/m, style('XXX'))
|
||||
.replace(/^(.*)\s*XXX$/m, style('XXX'))
|
||||
.replace(/(\s*)ASAP(\s*)/m, '$1<span class="ASAP">ASAP</span>$2')
|
||||
.replace(/^(?<!\\)>\s+(.*)$/m, style('quote'))
|
||||
.replace(/^(?<!\\)((\/\/|;)\s+.*)$/m, style('comment'))
|
||||
.replace(/^(?<!\\)XXX\s+(.*)$/m, style('XXX'))
|
||||
.replace(/^(.*)\s*(?<!\\)XXX$/m, style('XXX'))
|
||||
.replace(/(\s*)(?<!\\)ASAP(\s*)/m, '$1<span class="ASAP">ASAP</span>$2')
|
||||
// elements...
|
||||
.replace(/(\n|^)---*\h*(\n|$)/m, '$1<hr>')
|
||||
.replace(/(\n|^)(?<!\\)---*\h*(\n|$)/m, '$1<hr>')
|
||||
// ToDo...
|
||||
.replace(/^TODO\s*/m, style('todo', '<input type="checkbox">'))
|
||||
.replace(/^DONE\s*/m, style('todo', '<input type="checkbox" checked>'))
|
||||
.replace(/^(?<!\\)TODO\s+/m,
|
||||
style('todo', '<input type="checkbox">'))
|
||||
.replace(/^(?<!\\)DONE\s+/m,
|
||||
style('todo', '<input type="checkbox" checked>'))
|
||||
// checkboxes...
|
||||
.replace(/\[_\]/gm, style('check', '<input class="check" type="checkbox">'))
|
||||
.replace(/\[[X]\]/gm, style('check', '<input class="check" type="checkbox" checked>'))
|
||||
.replace(/(?<!\\)\[_\]/gm,
|
||||
style('check', '<input class="check" type="checkbox">'))
|
||||
.replace(/(?<!\\)\[[X]\]/gm,
|
||||
style('check', '<input class="check" type="checkbox" checked>'))
|
||||
// basic styling...
|
||||
// XXX these are quite naive...
|
||||
.replace(/\*(.*)\*/gm, '<b>$1</b>')
|
||||
.replace(/~([^~]*)~/gm, '<s>$1</s>')
|
||||
.replace(/_([^_]*)_/gm, '<i>$1</i>')
|
||||
.replace(/(?<!\\)\*(?=[^\s*])(([^*]|\\\*)*[^\s*])(?<!\\)\*/gm, '<b>$1</b>')
|
||||
.replace(/(?<!\\)~(?=[^\s~])(([^~]|\\~)*[^\s~])(?<!\\)~/gm, '<s>$1</s>')
|
||||
.replace(/(?<!\\)_(?=[^\s_])(([^_]|\\_)*[^\s_])(?<!\\)_/gm, '<i>$1</i>')
|
||||
.replace(/(?<!\\)`(?=[^\s_])(([^`]|\\`)*[^\s_])(?<!\\)`/gm, '<code>$1</code>')
|
||||
// quoting...
|
||||
.replace(/(?<!\\)\\(.)/gm, '$1')
|
||||
return elem },
|
||||
// XXX essentially here we need to remove service stuff like some
|
||||
// attributes (collapsed, id, ...)...
|
||||
// XXX also need to quote leading '- ' in block text here...
|
||||
// e.g.
|
||||
// - block
|
||||
// some text
|
||||
// - text in the above block ('-' needs to be quoted)
|
||||
// - next block
|
||||
__code2text__: function(code){
|
||||
// XXX
|
||||
},
|
||||
__text2code__: function(text){
|
||||
// XXX
|
||||
},
|
||||
|
||||
// serialization...
|
||||
data: function(elem, deep=true){
|
||||
elem = this.get(elem)
|
||||
return {
|
||||
text: elem.querySelector('textarea').value,
|
||||
collapsed: elem.getAttribute('collapsed') != null,
|
||||
...(deep ?
|
||||
{children: this.json(elem)}
|
||||
: {}),
|
||||
} },
|
||||
json: function(node){
|
||||
var that = this
|
||||
node ??= this.outline
|
||||
@ -349,11 +379,7 @@ var Outline = {
|
||||
.map(function(elem){
|
||||
return elem.nodeName != 'DIV' ?
|
||||
[]
|
||||
: [{
|
||||
text: elem.querySelector('textarea').value,
|
||||
collapsed: elem.getAttribute('collapsed') != null,
|
||||
children: that.json(elem)
|
||||
}] })
|
||||
: [that.data(elem)] })
|
||||
.flat() },
|
||||
// XXX add option to customize indent size...
|
||||
text: function(node, indent, level){
|
||||
@ -623,7 +649,6 @@ var Outline = {
|
||||
// click: left of elem (outside)
|
||||
if(evt.offsetX < 0){
|
||||
// XXX item menu?
|
||||
console.log('---', elem)
|
||||
|
||||
// click: right of elem (outside)
|
||||
} else if(elem.offsetWidth < evt.offsetX){
|
||||
@ -661,6 +686,13 @@ var Outline = {
|
||||
// heboard handling...
|
||||
outline.addEventListener('keydown',
|
||||
function(evt){
|
||||
var elem = evt.target
|
||||
// update element state...
|
||||
if(elem.nodeName == 'TEXTAREA'){
|
||||
setTimeout(function(){
|
||||
that.update(elem.parentElement)
|
||||
elem.updateSize() }, 0) }
|
||||
// handle keyboard...
|
||||
evt.key in that.keyboard
|
||||
&& that.keyboard[evt.key].call(that, evt) })
|
||||
// toggle view/code of nodes...
|
||||
@ -726,7 +758,9 @@ var Outline = {
|
||||
// code...
|
||||
var code = this.code
|
||||
if(code){
|
||||
this.load(code.innerHTML) }
|
||||
this.load(code.innerHTML
|
||||
.replace(/</g, '<')
|
||||
.replace(/>/g, '>')) }
|
||||
|
||||
return this },
|
||||
}
|
||||
|
||||
@ -27,7 +27,7 @@ var setup = function(){
|
||||
<body onload="setup()">
|
||||
<div class="editor">
|
||||
<!-- code -->
|
||||
<div class="code">
|
||||
<pre class="code">
|
||||
- # Outline editor prototype
|
||||
- An outline-based markdown editor experiment
|
||||
- ### Infuences::
|
||||
@ -36,18 +36,30 @@ var setup = function(){
|
||||
- Bonsai
|
||||
-
|
||||
- ## ToDo
|
||||
- shifting nodes up/down
|
||||
- editor: bksapce/del at start/end of a block should join it with prev/next
|
||||
- editor: pressing enter in text edit mode should split text into two blocks
|
||||
- ASAP: editor: bksapce/del at start/end of a block should join it with prev/next
|
||||
- ASAP: editor: pressing enter in text edit mode should split text into two blocks
|
||||
- ASAP: editor: shifting nodes up/down
|
||||
- ASAP: editor: `-` at start of line is interpreted as block marker...
|
||||
- editor: caret
|
||||
- ~go to next/prev element's start/end when moving off last/first char~
|
||||
- handle up/down on wrapped blocks
|
||||
_...can't seem to get caret line in a non-hacky way_
|
||||
- ~editor: semi-live update styles~
|
||||
- need to reach checkboxes via keyboard
|
||||
- persistent empty first/last node (a button to create a new node)
|
||||
- add completion percentage to blocks with todo's nested
|
||||
either by default oron '%%' or '[%]' placeholder
|
||||
...ratio between all nested open checkboxes to checked (???)
|
||||
- add completion percentage to blocks with todo's nested:
|
||||
- `[%]`, `%%`, or something similar...
|
||||
- read-only mode
|
||||
- should bulets be on the same level as nodes or offset??
|
||||
- A) justified to bulet:
|
||||
* list item
|
||||
* list item
|
||||
block text
|
||||
- B) justified to text _(current)_:
|
||||
* list item
|
||||
* list item
|
||||
block text
|
||||
- NOTE: this is only a problem if making list-items manually -- disable???
|
||||
- ~do a better expand/collapse icons~
|
||||
- ~loading from DOM -- fill textarea~
|
||||
- ~focus management~
|
||||
@ -65,7 +77,8 @@ var setup = function(){
|
||||
- edit node
|
||||
- markdown: tables
|
||||
- empty item height is a bit off...
|
||||
- ~serialize~/deserialize
|
||||
- handle links gracefully
|
||||
- ~serialize/deserialize~
|
||||
- ~add optional text styling to nodes~
|
||||
-
|
||||
- ## TEST
|
||||
@ -82,6 +95,7 @@ var setup = function(){
|
||||
- a
|
||||
- b
|
||||
- c
|
||||
- > quoted text
|
||||
- // C-style comment
|
||||
- ; ASM-style comment
|
||||
- XXX Highlight
|
||||
@ -96,6 +110,13 @@ var setup = function(){
|
||||
- DONE done item
|
||||
- [_] a different way to draw a checkbox
|
||||
- Inline [X] checkboxes [_]
|
||||
- link <a href="about:blank">example</a>
|
||||
- markdown:
|
||||
- code blocks
|
||||
- numbered lists
|
||||
- alerts
|
||||
- tables
|
||||
- footnotes??
|
||||
-
|
||||
- ### Playground for testing
|
||||
- A
|
||||
@ -110,11 +131,11 @@ var setup = function(){
|
||||
- This is a line of text
|
||||
- This is a set
|
||||
text lines
|
||||
- Lots of text Lots of text Lots of text Lots of text Lots of text Lots of text Lots of text Lots of text Lots of text Lots of text Lots of text Lots of text Lots of text Lots of text Lots of text Lots of text Lots of text Lots of text Lots of text Lots of text Lots of text Lots of text Lots of text Lots of text Lots of text </div>
|
||||
- Lots of text Lots of text Lots of text Lots of text Lots of text Lots of text Lots of text Lots of text Lots of text Lots of text Lots of text Lots of text Lots of text Lots of text Lots of text Lots of text Lots of text Lots of text Lots of text Lots of text Lots of text Lots of text Lots of text Lots of text Lots of text </pre>
|
||||
<!-- outline -->
|
||||
<div class="outline"></div>
|
||||
<!-- toolbar (optional) -->
|
||||
<div class="toolbar">
|
||||
<!--div class="toolbar">
|
||||
<button onclick="editor.deindent().focus()"><</button>
|
||||
<button onclick="editor.indent().focus()">></button>
|
||||
<button onclick="editor.Block('before').focus()" class="add-row">+</button>
|
||||
@ -122,7 +143,7 @@ var setup = function(){
|
||||
<button onclick="editor.Block('after').focus()" class="add-row">+</button>
|
||||
<button onclick="editor.toggleCollapse()?.focus()">˅˄</button>
|
||||
<button onclick="editor.remove()">×</button>
|
||||
</div>
|
||||
</div-->
|
||||
</div>
|
||||
|
||||
<hr>
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user