mirror of
https://github.com/flynx/pWiki.git
synced 2025-12-25 04:11:56 +00:00
Compare commits
No commits in common. "7f2b027a7be4160206752c5b8ddebe4c70204b43" and "9b2b232f691b787e5fe7e0899607c1986dcf2c83" have entirely different histories.
7f2b027a7b
...
9b2b232f69
@ -110,59 +110,14 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* Styles */
|
.editor .outline h1,
|
||||||
|
.editor .outline h2,
|
||||||
.editor .outline .heading-1>span,
|
.editor .outline h3,
|
||||||
.editor .outline .heading-1>textarea,
|
.editor .outline h4,
|
||||||
.editor .outline .heading-2>span,
|
.editor .outline h5,
|
||||||
.editor .outline .heading-2>textarea,
|
.editor .outline h6 {
|
||||||
.editor .outline .heading-3>span,
|
margin-top: 0.5em;
|
||||||
.editor .outline .heading-3>textarea,
|
margin-bottom: 0.5em;
|
||||||
.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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@ -75,7 +75,6 @@ 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(){
|
||||||
@ -216,30 +215,6 @@ 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){
|
||||||
@ -309,27 +284,10 @@ 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...
|
||||||
@ -338,22 +296,38 @@ var Outline = {
|
|||||||
elem.collapsed = value.trim() == 'true'
|
elem.collapsed = value.trim() == 'true'
|
||||||
return '' })
|
return '' })
|
||||||
// markdown...
|
// markdown...
|
||||||
.replace(/^TODO\s*(.*)$/, '<input type="checkbox"> $1')
|
.replace(/^######\s*(.*)\s*(\n|$)/, '<h6>$1</h6>')
|
||||||
.replace(/^DONE\s*(.*)$/, '<input type="checkbox" checked> $1')
|
.replace(/^#####\s*(.*)\s*(\n|$)/, '<h5>$1</h5>')
|
||||||
.replace(/^######\s*(.*)$/, style('heading-6'))
|
.replace(/^####\s*(.*)\s*(\n|$)/, '<h4>$1</h4>')
|
||||||
.replace(/^#####\s*(.*)$/, style('heading-5'))
|
.replace(/^###\s*(.*)\s*(\n|$)/, '<h3>$1</h3>')
|
||||||
.replace(/^####\s*(.*)$/, style('heading-4'))
|
.replace(/^##\s*(.*)\s*(\n|$)/, '<h2>$1</h2>')
|
||||||
.replace(/^###\s*(.*)$/, style('heading-3'))
|
.replace(/^#\s*(.*)\s*(\n|$)/, '<h1>$1</h1>')
|
||||||
.replace(/^##\s*(.*)$/, style('heading-2'))
|
|
||||||
.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){
|
||||||
@ -364,12 +338,13 @@ var Outline = {
|
|||||||
return elem.nodeName != 'DIV' ?
|
return elem.nodeName != 'DIV' ?
|
||||||
[]
|
[]
|
||||||
: [{
|
: [{
|
||||||
text: elem.querySelector('textarea').value,
|
text: that.__html2code__ ?
|
||||||
|
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'){
|
||||||
@ -400,10 +375,9 @@ 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].replace(/\t/g, tab)
|
sep = lst[0]
|
||||||
// deindent...
|
// deindent...
|
||||||
if(prev_sep != null
|
if(prev_sep != null
|
||||||
&& sep.length < prev_sep.length){
|
&& sep.length < prev_sep.length){
|
||||||
@ -437,10 +411,19 @@ 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)
|
||||||
this.update(block, data)
|
if(data.text){
|
||||||
|
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)
|
||||||
@ -613,14 +596,23 @@ 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'){
|
||||||
var block = node.parentElement
|
if(that.__code2html__){
|
||||||
that.update(block, { text: node.value }) } })
|
var data = that.__code2html__(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',
|
||||||
@ -630,6 +622,7 @@ 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,10 +28,6 @@ var setup = function(){
|
|||||||
<div class="code">
|
<div class="code">
|
||||||
- # Outline editor prototype
|
- # Outline editor prototype
|
||||||
- ## TODO
|
- ## TODO
|
||||||
- BUG: delete in edit mode deletes node
|
|
||||||
- BUG: multiline blocks do not indent correctly in editor
|
|
||||||
- make checkboxes clickable
|
|
||||||
- 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
|
||||||
@ -39,7 +35,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~
|
||||||
@ -58,25 +54,6 @@ 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
|
|
||||||
- line
|
|
||||||
- ---
|
|
||||||
- basic inline *bold*, _italic_ and ~striked~
|
|
||||||
- To do items
|
|
||||||
- TODO undone item
|
|
||||||
- DONE done item
|
|
||||||
- A
|
- A
|
||||||
collapsed:: true
|
collapsed:: true
|
||||||
- a
|
- a
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user