mirror of
https://github.com/flynx/pWiki.git
synced 2025-11-01 03:20:08 +00:00
code cleanup + notes...
Signed-off-by: Alex A. Naanou <alex.nanou@gmail.com>
This commit is contained in:
parent
9b2b232f69
commit
6633bc065a
@ -110,6 +110,56 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
.editor .outline .heading-1>span,
|
||||||
|
.editor .outline .heading-1>textarea,
|
||||||
|
.editor .outline .heading-2>span,
|
||||||
|
.editor .outline .heading-2>textarea,
|
||||||
|
.editor .outline .heading-3>span,
|
||||||
|
.editor .outline .heading-3>textarea,
|
||||||
|
.editor .outline .heading-4>span,
|
||||||
|
.editor .outline .heading-4>textarea,
|
||||||
|
.editor .outline .heading-5>span,
|
||||||
|
.editor .outline .heading-5>textarea,
|
||||||
|
.editor .outline .heading-6>span,
|
||||||
|
.editor .outline .heading-6>textarea {
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
.editor .outline .heading-1>span,
|
||||||
|
.editor .outline .heading-1>textarea {
|
||||||
|
font-size: 2.5em;
|
||||||
|
}
|
||||||
|
.editor .outline .heading-2>span,
|
||||||
|
.editor .outline .heading-2>textarea {
|
||||||
|
font-size: 1.9em;
|
||||||
|
}
|
||||||
|
.editor .outline .heading-3>span,
|
||||||
|
.editor .outline .heading-3>textarea {
|
||||||
|
font-size: 1.5em;
|
||||||
|
}
|
||||||
|
.editor .outline .heading-4>span,
|
||||||
|
.editor .outline .heading-4>textarea {
|
||||||
|
font-size: 1.3em;
|
||||||
|
}
|
||||||
|
.editor .outline .heading-5>span,
|
||||||
|
.editor .outline .heading-5>textarea {
|
||||||
|
font-size: 1.1em;
|
||||||
|
}
|
||||||
|
.editor .outline .heading-6>span,
|
||||||
|
.editor .outline .heading-6>textarea {
|
||||||
|
font-size: 1em;
|
||||||
|
}
|
||||||
|
/* XXX EXPERIMENTAL -- not sure about this... */
|
||||||
|
.editor .outline .list>[tabindex]:before {
|
||||||
|
display: inline-block;
|
||||||
|
position: absolute;
|
||||||
|
content: "";
|
||||||
|
top: 0.6em;
|
||||||
|
left: -0.8em;
|
||||||
|
width: 0.5em;
|
||||||
|
height: 0.5em;
|
||||||
|
background: silver;
|
||||||
|
}
|
||||||
|
|
||||||
.editor .outline h1,
|
.editor .outline h1,
|
||||||
.editor .outline h2,
|
.editor .outline h2,
|
||||||
.editor .outline h3,
|
.editor .outline h3,
|
||||||
@ -121,3 +171,5 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@ -75,6 +75,7 @@ var Outline = {
|
|||||||
left_key_collapses: true,
|
left_key_collapses: true,
|
||||||
right_key_expands: true,
|
right_key_expands: true,
|
||||||
code_update_interval: 5000,
|
code_update_interval: 5000,
|
||||||
|
tab_size: 4,
|
||||||
|
|
||||||
|
|
||||||
get code(){
|
get code(){
|
||||||
@ -215,6 +216,30 @@ var Outline = {
|
|||||||
focus: function(node='focused', offset){},
|
focus: function(node='focused', offset){},
|
||||||
edit: 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.collapsed ?
|
||||||
|
node.setAttribute('collapsed', '')
|
||||||
|
: node.removeAttribute('collapsed')
|
||||||
|
if(data.text){
|
||||||
|
var text = node.querySelector('textarea')
|
||||||
|
var html = node.querySelector('span')
|
||||||
|
if(this.__code2html__){
|
||||||
|
// NOTE: we are ignoring the .collapsed attr here
|
||||||
|
var parsed = this.__code2html__(data.text)
|
||||||
|
html.innerHTML = parsed.text
|
||||||
|
// heading...
|
||||||
|
parsed.style ?
|
||||||
|
node.classList.add(parsed.style)
|
||||||
|
: node.classList.remove(...this.__styles__)
|
||||||
|
} else {
|
||||||
|
html.innerHTML = data.text }
|
||||||
|
text.value = data.text
|
||||||
|
// XXX this does not see to work until we click in the textarea...
|
||||||
|
text.autoUpdateSize() }
|
||||||
|
return node },
|
||||||
|
|
||||||
indent: function(node='focused', indent=true){
|
indent: function(node='focused', indent=true){
|
||||||
// .indent(<indent>)
|
// .indent(<indent>)
|
||||||
if(node === true || node === false){
|
if(node === true || node === false){
|
||||||
@ -284,10 +309,27 @@ var Outline = {
|
|||||||
// XXX STUB...
|
// XXX STUB...
|
||||||
// XXX shouild we support headings + other formatting per block???
|
// XXX shouild we support headings + other formatting per block???
|
||||||
// XXX these should be symetrical -- now one returns text the other an object...
|
// XXX these should be symetrical -- now one returns text the other an object...
|
||||||
|
__styles__: [
|
||||||
|
'heading-1',
|
||||||
|
'heading-2',
|
||||||
|
'heading-3',
|
||||||
|
'heading-4',
|
||||||
|
'heading-5',
|
||||||
|
'heading-6',
|
||||||
|
'list',
|
||||||
|
],
|
||||||
__code2html__: function(code){
|
__code2html__: function(code){
|
||||||
var elem = {
|
var elem = {
|
||||||
collapsed: false,
|
collapsed: false,
|
||||||
}
|
}
|
||||||
|
var heading = function(level){
|
||||||
|
return function(_, text){
|
||||||
|
elem.style = 'heading-'+level
|
||||||
|
return text } }
|
||||||
|
var style = function(style){
|
||||||
|
return function(_, text){
|
||||||
|
elem.style = style
|
||||||
|
return text } }
|
||||||
elem.text = code
|
elem.text = code
|
||||||
// attributes...
|
// attributes...
|
||||||
// XXX make this generic...
|
// XXX make this generic...
|
||||||
@ -296,38 +338,20 @@ var Outline = {
|
|||||||
elem.collapsed = value.trim() == 'true'
|
elem.collapsed = value.trim() == 'true'
|
||||||
return '' })
|
return '' })
|
||||||
// markdown...
|
// markdown...
|
||||||
.replace(/^######\s*(.*)\s*(\n|$)/, '<h6>$1</h6>')
|
.replace(/^######\s*(.*)$/, style('heading-6'))
|
||||||
.replace(/^#####\s*(.*)\s*(\n|$)/, '<h5>$1</h5>')
|
.replace(/^#####\s*(.*)$/, style('heading-5'))
|
||||||
.replace(/^####\s*(.*)\s*(\n|$)/, '<h4>$1</h4>')
|
.replace(/^####\s*(.*)$/, style('heading-4'))
|
||||||
.replace(/^###\s*(.*)\s*(\n|$)/, '<h3>$1</h3>')
|
.replace(/^###\s*(.*)$/, style('heading-3'))
|
||||||
.replace(/^##\s*(.*)\s*(\n|$)/, '<h2>$1</h2>')
|
.replace(/^##\s*(.*)$/, style('heading-2'))
|
||||||
.replace(/^#\s*(.*)\s*(\n|$)/, '<h1>$1</h1>')
|
.replace(/^#\s*(.*)$/, style('heading-1'))
|
||||||
|
//.replace(/^[-\*]\s*(.*)$/, style('list'))
|
||||||
|
.replace(/^\s*(.*):\s*$/, style('list'))
|
||||||
.replace(/\*(.*)\*/g, '<b>$1</b>')
|
.replace(/\*(.*)\*/g, '<b>$1</b>')
|
||||||
.replace(/~([^~]*)~/g, '<s>$1</s>')
|
.replace(/~([^~]*)~/g, '<s>$1</s>')
|
||||||
.replace(/_([^_]*)_/g, '<i>$1</i>')
|
.replace(/_([^_]*)_/g, '<i>$1</i>')
|
||||||
.replace(/(\n|^)---*\h*(\n|$)/, '$1<hr>')
|
.replace(/(\n|^)---*\h*(\n|$)/, '$1<hr>')
|
||||||
.replace(/\n/g, '<br>\n')
|
.replace(/\n/g, '<br>\n')
|
||||||
return elem },
|
return elem },
|
||||||
__html2code__: function(html){
|
|
||||||
var heading = function(level){
|
|
||||||
return function(_, text, rest){
|
|
||||||
return `${'#'.repeat(level)} ${text}${
|
|
||||||
(rest != '' ?
|
|
||||||
'\n'+ rest
|
|
||||||
: '') }` } }
|
|
||||||
return html
|
|
||||||
.replace(/<hr>$/, '---')
|
|
||||||
.replace(/<hr>/, '---\n')
|
|
||||||
.replace(/^<h6>(.*)<\/h6>(.*)$/g, heading(6))
|
|
||||||
.replace(/^<h5>(.*)<\/h5>(.*)$/g, heading(5))
|
|
||||||
.replace(/^<h4>(.*)<\/h4>(.*)$/g, heading(4))
|
|
||||||
.replace(/^<h3>(.*)<\/h3>(.*)$/g, heading(3))
|
|
||||||
.replace(/^<h2>(.*)<\/h2>(.*)$/g, heading(2))
|
|
||||||
.replace(/^<h1>(.*)<\/h1>(.*)$/g, heading(1))
|
|
||||||
.replace(/<b>(.*)<\/b>/g, '*$1*')
|
|
||||||
.replace(/<s>(.*)<\/s>/g, '~$1~')
|
|
||||||
.replace(/<i>(.*)<\/i>/g, '_$1_')
|
|
||||||
.replace(/<br>\s*/g, '\n') },
|
|
||||||
|
|
||||||
// serialization...
|
// serialization...
|
||||||
json: function(node){
|
json: function(node){
|
||||||
@ -338,13 +362,12 @@ var Outline = {
|
|||||||
return elem.nodeName != 'DIV' ?
|
return elem.nodeName != 'DIV' ?
|
||||||
[]
|
[]
|
||||||
: [{
|
: [{
|
||||||
text: that.__html2code__ ?
|
text: elem.querySelector('textarea').value,
|
||||||
that.__html2code__(elem.querySelector('span').innerHTML)
|
|
||||||
: elem.querySelector('span').innerHTML,
|
|
||||||
collapsed: elem.getAttribute('collapsed') != null,
|
collapsed: elem.getAttribute('collapsed') != null,
|
||||||
children: that.json(elem)
|
children: that.json(elem)
|
||||||
}] })
|
}] })
|
||||||
.flat() },
|
.flat() },
|
||||||
|
// XXX add option to customize indent size...
|
||||||
text: function(node, indent, level){
|
text: function(node, indent, level){
|
||||||
// .text(<indent>, <level>)
|
// .text(<indent>, <level>)
|
||||||
if(typeof(node) == 'string'){
|
if(typeof(node) == 'string'){
|
||||||
@ -375,9 +398,10 @@ var Outline = {
|
|||||||
text = ('\n' + text)
|
text = ('\n' + text)
|
||||||
.split(/\n(\s*)- /g)
|
.split(/\n(\s*)- /g)
|
||||||
.slice(1)
|
.slice(1)
|
||||||
|
var tab = ' '.repeat(this.tab_size || 8)
|
||||||
var level = function(lst, prev_sep=undefined, parent=[]){
|
var level = function(lst, prev_sep=undefined, parent=[]){
|
||||||
while(lst.length > 0){
|
while(lst.length > 0){
|
||||||
sep = lst[0]
|
sep = lst[0].replace(/\t/g, tab)
|
||||||
// deindent...
|
// deindent...
|
||||||
if(prev_sep != null
|
if(prev_sep != null
|
||||||
&& sep.length < prev_sep.length){
|
&& sep.length < prev_sep.length){
|
||||||
@ -411,19 +435,10 @@ var Outline = {
|
|||||||
data = {} }
|
data = {} }
|
||||||
var block = document.createElement('div')
|
var block = document.createElement('div')
|
||||||
block.setAttribute('tabindex', '0')
|
block.setAttribute('tabindex', '0')
|
||||||
data.collapsed
|
|
||||||
&& block.setAttribute('collapsed', '')
|
|
||||||
var text = document.createElement('textarea')
|
var text = document.createElement('textarea')
|
||||||
var html = document.createElement('span')
|
var html = document.createElement('span')
|
||||||
block.append(text, html)
|
block.append(text, html)
|
||||||
if(data.text){
|
this.update(block, data)
|
||||||
html.innerHTML = this.__code2html__ ?
|
|
||||||
// NOTE: we are ignoring the .collapsed attr here (XXX)
|
|
||||||
this.__code2html__(data.text).text
|
|
||||||
: data.text
|
|
||||||
text.value = data.text
|
|
||||||
// XXX this does not see to work until we click in the textarea...
|
|
||||||
text.autoUpdateSize() }
|
|
||||||
var cur = this.get()
|
var cur = this.get()
|
||||||
place && cur
|
place && cur
|
||||||
&& cur[place](block)
|
&& cur[place](block)
|
||||||
@ -596,23 +611,14 @@ var Outline = {
|
|||||||
// textarea...
|
// textarea...
|
||||||
if(node.nodeName == 'TEXTAREA'
|
if(node.nodeName == 'TEXTAREA'
|
||||||
&& node?.nextElementSibling?.nodeName == 'SPAN'){
|
&& node?.nextElementSibling?.nodeName == 'SPAN'){
|
||||||
node.value =
|
|
||||||
that.__html2code__ ?
|
|
||||||
that.__html2code__(node.nextElementSibling.innerHTML)
|
|
||||||
: node.nextElementSibling.innerHTML
|
|
||||||
node.updateSize() } })
|
node.updateSize() } })
|
||||||
outline.addEventListener('focusout',
|
outline.addEventListener('focusout',
|
||||||
function(evt){
|
function(evt){
|
||||||
var node = evt.target
|
var node = evt.target
|
||||||
if(node.nodeName == 'TEXTAREA'
|
if(node.nodeName == 'TEXTAREA'
|
||||||
&& node?.nextElementSibling?.nodeName == 'SPAN'){
|
&& node?.nextElementSibling?.nodeName == 'SPAN'){
|
||||||
if(that.__code2html__){
|
var block = node.parentElement
|
||||||
var data = that.__code2html__(node.value)
|
that.update(block, { text: node.value }) } })
|
||||||
node.nextElementSibling.innerHTML = data.text
|
|
||||||
data.collapsed
|
|
||||||
&& node.parentElement.setAttribute('collapsed', '')
|
|
||||||
} else {
|
|
||||||
node.nextElementSibling.innerHTML = node.value } } })
|
|
||||||
// update .code...
|
// update .code...
|
||||||
var update_code_timeout
|
var update_code_timeout
|
||||||
outline.addEventListener('change',
|
outline.addEventListener('change',
|
||||||
@ -622,7 +628,6 @@ var Outline = {
|
|||||||
update_code_timeout = setTimeout(
|
update_code_timeout = setTimeout(
|
||||||
function(){
|
function(){
|
||||||
update_code_timeout = undefined
|
update_code_timeout = undefined
|
||||||
console.log('SYNC')
|
|
||||||
that.sync() },
|
that.sync() },
|
||||||
that.code_update_interval || 5000) })
|
that.code_update_interval || 5000) })
|
||||||
|
|
||||||
|
|||||||
@ -28,6 +28,8 @@ var setup = function(){
|
|||||||
<div class="code">
|
<div class="code">
|
||||||
- # Outline editor prototype
|
- # Outline editor prototype
|
||||||
- ## TODO
|
- ## TODO
|
||||||
|
- BUG: delete in edit mode deletes node...
|
||||||
|
- editor: enter on an expanded parent node should create child (currently next sibling)
|
||||||
- editor: bksapce/del at start/end of a block should join it with prev/next
|
- 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
|
- editor: pressing enter in text edit mode should split text into two blocks
|
||||||
- editor: caret
|
- editor: caret
|
||||||
@ -35,7 +37,7 @@ var setup = function(){
|
|||||||
- handle up/down on wrapped blocks
|
- handle up/down on wrapped blocks
|
||||||
_...can't seem to get caret line in a non-hacky way_
|
_...can't seem to get caret line in a non-hacky way_
|
||||||
- persistent empty first/last node (a button to create a new node)
|
- persistent empty first/last node (a button to create a new node)
|
||||||
- loading from DOM -- fill textarea
|
- ~loading from DOM -- fill textarea~
|
||||||
- ~focus management~
|
- ~focus management~
|
||||||
- ~mouse/touch controls~
|
- ~mouse/touch controls~
|
||||||
- ~navigation~
|
- ~navigation~
|
||||||
@ -54,6 +56,20 @@ var setup = function(){
|
|||||||
- ~add optional text styling to nodes~
|
- ~add optional text styling to nodes~
|
||||||
-
|
-
|
||||||
- ## TEST
|
- ## TEST
|
||||||
|
- Formatting
|
||||||
|
- Styles
|
||||||
|
- # Heading 1
|
||||||
|
- ## Heading 2
|
||||||
|
- ### Heading 3
|
||||||
|
- #### Heading 4
|
||||||
|
- ##### Heading 5
|
||||||
|
- ###### Heading 6
|
||||||
|
- Text
|
||||||
|
- List::
|
||||||
|
- a
|
||||||
|
- b
|
||||||
|
- c
|
||||||
|
- basic inline *bold*, _italic_ and ~striked~
|
||||||
- A
|
- A
|
||||||
collapsed:: true
|
collapsed:: true
|
||||||
- a
|
- a
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user