From 6633bc065af7280abeaa4d8c9fb95156bd370399 Mon Sep 17 00:00:00 2001 From: "Alex A. Naanou" Date: Sun, 8 Oct 2023 02:36:29 +0300 Subject: [PATCH] code cleanup + notes... Signed-off-by: Alex A. Naanou --- experiments/outline-editor/editor.css | 52 ++++++++++++ experiments/outline-editor/editor.js | 109 ++++++++++++++------------ experiments/outline-editor/index.html | 18 ++++- 3 files changed, 126 insertions(+), 53 deletions(-) diff --git a/experiments/outline-editor/editor.css b/experiments/outline-editor/editor.css index 0056af5..fb9e294 100755 --- a/experiments/outline-editor/editor.css +++ b/experiments/outline-editor/editor.css @@ -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 h2, .editor .outline h3, @@ -121,3 +171,5 @@ } + + diff --git a/experiments/outline-editor/editor.js b/experiments/outline-editor/editor.js index ba74189..873d8b3 100755 --- a/experiments/outline-editor/editor.js +++ b/experiments/outline-editor/editor.js @@ -75,6 +75,7 @@ var Outline = { left_key_collapses: true, right_key_expands: true, code_update_interval: 5000, + tab_size: 4, get code(){ @@ -215,6 +216,30 @@ 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.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() if(node === true || node === false){ @@ -284,10 +309,27 @@ var Outline = { // XXX STUB... // XXX shouild we support headings + other formatting per block??? // 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){ var elem = { 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 // attributes... // XXX make this generic... @@ -296,38 +338,20 @@ var Outline = { elem.collapsed = value.trim() == 'true' return '' }) // markdown... - .replace(/^######\s*(.*)\s*(\n|$)/, '
$1
') - .replace(/^#####\s*(.*)\s*(\n|$)/, '
$1
') - .replace(/^####\s*(.*)\s*(\n|$)/, '

$1

') - .replace(/^###\s*(.*)\s*(\n|$)/, '

$1

') - .replace(/^##\s*(.*)\s*(\n|$)/, '

$1

') - .replace(/^#\s*(.*)\s*(\n|$)/, '

$1

') + .replace(/^######\s*(.*)$/, style('heading-6')) + .replace(/^#####\s*(.*)$/, style('heading-5')) + .replace(/^####\s*(.*)$/, style('heading-4')) + .replace(/^###\s*(.*)$/, style('heading-3')) + .replace(/^##\s*(.*)$/, style('heading-2')) + .replace(/^#\s*(.*)$/, style('heading-1')) + //.replace(/^[-\*]\s*(.*)$/, style('list')) + .replace(/^\s*(.*):\s*$/, style('list')) .replace(/\*(.*)\*/g, '$1') .replace(/~([^~]*)~/g, '$1') .replace(/_([^_]*)_/g, '$1') .replace(/(\n|^)---*\h*(\n|$)/, '$1
') .replace(/\n/g, '
\n') return elem }, - __html2code__: function(html){ - var heading = function(level){ - return function(_, text, rest){ - return `${'#'.repeat(level)} ${text}${ - (rest != '' ? - '\n'+ rest - : '') }` } } - return html - .replace(/
$/, '---') - .replace(/
/, '---\n') - .replace(/^
(.*)<\/h6>(.*)$/g, heading(6)) - .replace(/^
(.*)<\/h5>(.*)$/g, heading(5)) - .replace(/^

(.*)<\/h4>(.*)$/g, heading(4)) - .replace(/^

(.*)<\/h3>(.*)$/g, heading(3)) - .replace(/^

(.*)<\/h2>(.*)$/g, heading(2)) - .replace(/^

(.*)<\/h1>(.*)$/g, heading(1)) - .replace(/(.*)<\/b>/g, '*$1*') - .replace(/(.*)<\/s>/g, '~$1~') - .replace(/(.*)<\/i>/g, '_$1_') - .replace(/
\s*/g, '\n') }, // serialization... json: function(node){ @@ -338,13 +362,12 @@ var Outline = { return elem.nodeName != 'DIV' ? [] : [{ - text: that.__html2code__ ? - that.__html2code__(elem.querySelector('span').innerHTML) - : elem.querySelector('span').innerHTML, + text: elem.querySelector('textarea').value, collapsed: elem.getAttribute('collapsed') != null, children: that.json(elem) }] }) .flat() }, + // XXX add option to customize indent size... text: function(node, indent, level){ // .text(, ) if(typeof(node) == 'string'){ @@ -375,9 +398,10 @@ var Outline = { text = ('\n' + text) .split(/\n(\s*)- /g) .slice(1) + var tab = ' '.repeat(this.tab_size || 8) var level = function(lst, prev_sep=undefined, parent=[]){ while(lst.length > 0){ - sep = lst[0] + sep = lst[0].replace(/\t/g, tab) // deindent... if(prev_sep != null && sep.length < prev_sep.length){ @@ -411,19 +435,10 @@ var Outline = { data = {} } var block = document.createElement('div') block.setAttribute('tabindex', '0') - data.collapsed - && block.setAttribute('collapsed', '') var text = document.createElement('textarea') var html = document.createElement('span') block.append(text, html) - 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() } + this.update(block, data) var cur = this.get() place && cur && cur[place](block) @@ -596,23 +611,14 @@ var Outline = { // textarea... if(node.nodeName == 'TEXTAREA' && node?.nextElementSibling?.nodeName == 'SPAN'){ - node.value = - that.__html2code__ ? - that.__html2code__(node.nextElementSibling.innerHTML) - : node.nextElementSibling.innerHTML node.updateSize() } }) outline.addEventListener('focusout', function(evt){ var node = evt.target if(node.nodeName == 'TEXTAREA' && node?.nextElementSibling?.nodeName == 'SPAN'){ - if(that.__code2html__){ - var data = that.__code2html__(node.value) - node.nextElementSibling.innerHTML = data.text - data.collapsed - && node.parentElement.setAttribute('collapsed', '') - } else { - node.nextElementSibling.innerHTML = node.value } } }) + var block = node.parentElement + that.update(block, { text: node.value }) } }) // update .code... var update_code_timeout outline.addEventListener('change', @@ -622,7 +628,6 @@ var Outline = { update_code_timeout = setTimeout( function(){ update_code_timeout = undefined - console.log('SYNC') that.sync() }, that.code_update_interval || 5000) }) diff --git a/experiments/outline-editor/index.html b/experiments/outline-editor/index.html index c037e2d..5e75988 100755 --- a/experiments/outline-editor/index.html +++ b/experiments/outline-editor/index.html @@ -28,6 +28,8 @@ var setup = function(){
- # Outline editor prototype - ## 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: pressing enter in text edit mode should split text into two blocks - editor: caret @@ -35,7 +37,7 @@ var setup = function(){ - handle up/down on wrapped blocks _...can't seem to get caret line in a non-hacky way_ - persistent empty first/last node (a button to create a new node) - - loading from DOM -- fill textarea + - ~loading from DOM -- fill textarea~ - ~focus management~ - ~mouse/touch controls~ - ~navigation~ @@ -54,6 +56,20 @@ var setup = function(){ - ~add optional text styling to nodes~ - - ## 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 collapsed:: true - a