diff --git a/experiments/outline-editor/editor.css b/experiments/outline-editor/editor.css
index 368b941..901d8e8 100755
--- a/experiments/outline-editor/editor.css
+++ b/experiments/outline-editor/editor.css
@@ -1,6 +1,7 @@
:root {
--font-size: 5mm;
+ --item-padding: 0.2em;
--button-size: 2em;
font-family: sans-serif;
@@ -36,14 +37,16 @@
}
.editor .outline [tabindex]>span,
.editor .outline [tabindex]>textarea {
- --padding: 0.2em;
-
display: block;
width: 100%;
/* XXX this is a tiny bit off and using textarea's height here is off too... */
min-height: 1em;
- padding: var(--padding);
+ padding-top: var(--item-padding);
+ padding-bottom: var(--item-padding);
+ padding-left: 0;
+ padding-right: 0;
margin: 0;
+ box-sizing: border-box;
font-family: sans-serif;
font-size: var(--font-size);
@@ -53,7 +56,7 @@
border: none;
}
.editor .outline [tabindex]>textarea {
- height: calc(2 * var(--padding) + 1em);
+ height: calc(2 * var(--item-padding) + 1em);
overflow: hidden;
resize: none;
}
@@ -130,6 +133,15 @@
.editor .outline .heading-6>textarea {
font-weight: bold;
}
+.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 {
+ border-bottom: solid 1px rgba(0,0,0,0.05);
+}
+
.editor .outline .heading-1>span,
.editor .outline .heading-1>textarea {
font-size: 2.5em;
@@ -155,16 +167,20 @@
font-size: 1em;
}
-/* XXX EXPERIMENTAL -- not sure about this... */
+/* XXX needs to be in the middle of the first span but with universal size... */
.editor .outline .list-item:before,
-.editor .outline .list>[tabindex]:before {
+.editor .outline .list>[tabindex]>span:before {
+ --size: 0.5rem;
+
display: inline-block;
position: absolute;
content: "";
- top: 0.6em;
- left: -0.8em;
- width: 0.5em;
- height: 0.5em;
+ top: calc(0.6em + var(--item-padding));
+ left: calc(var(--size) * -2);
+ width: var(--size);
+ height: var(--size);
+ margin-top: calc(var(--size) / -2);
+
background: silver;
}
@@ -172,15 +188,31 @@
background: yellow;
}
+.editor.hide-comments .outline .comment {
+ display: none;
+}
.editor .outline .comment>span {
color: silver;
}
-.editor .outline [tabindex]>span>input[type=checkbox] {
- --width: 3em;
+.editor .outline [tabindex]>span>input[type=checkbox].check,
+.editor .outline [tabindex]>span>input[type=checkbox].todo {
+ --size: 1.5rem;
+ --height: calc(var(--font-size) + 2 * var(--item-padding));
- height: 1em;
- width: var(--width);
- margin-left: calc(-1 * var(--width));
+ top: calc(0.6em + var(--item-padding));
+ height: var(--size);
+ width: var(--size);
+ margin-top: calc(var(--size) / -2);
+
+ /* NOTE: this appears to be needed for the em sizes above to work correctly */
+ font-size: 1em;
+}
+.editor .outline [tabindex]>span>input[type=checkbox].todo {
+ position: absolute;
+ margin-left: calc(-1 * var(--size) - var(--item-padding));
+}
+.editor .outline [tabindex]>span>input[type=checkbox].check {
+ transform: translateY(calc(2 * var(--item-padding)));
}
diff --git a/experiments/outline-editor/editor.js b/experiments/outline-editor/editor.js
index 47c1d75..a8d21c4 100755
--- a/experiments/outline-editor/editor.js
+++ b/experiments/outline-editor/editor.js
@@ -27,46 +27,8 @@ var atLine = function(elem, index){
//---------------------------------------------------------------------
-var Node = {
- dom: undefined,
- document: undefined,
-
- get: function(){},
-
- get root(){},
- get parent(){},
- get children(){},
- get next(){},
- get prev(){},
-
- focus: function(){},
- edit: function(){},
-
- indent: function(){ },
- deindent: function(){ },
- toggleCollapse: function(){ },
-
- remove: function(){},
-
- json: function(){},
- text: function(){},
-
- load: function(){},
-}
-
-var NodeGroup = {
- __proto__: Node,
-}
-
-// XXX should this be Page or root??
-var Root = {
- __proto__: NodeGroup,
-}
-
-
-// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-
-// XXX might be a good idea to do a view-action model...
+// XXX experiment with a concatinative model...
+// .get(..) -> Outline (view)
var Outline = {
dom: undefined,
@@ -219,9 +181,10 @@ var Outline = {
// XXX should this handle children???
update: function(node='focused', data){
var node = this.get(node)
- data.collapsed ?
- node.setAttribute('collapsed', '')
- : node.removeAttribute('collapsed')
+ typeof(data.collapsed) == 'boolean'
+ && (data.collapsed ?
+ node.setAttribute('collapsed', '')
+ : node.removeAttribute('collapsed'))
if(data.text){
var text = node.querySelector('textarea')
var html = node.querySelector('span')
@@ -231,7 +194,7 @@ var Outline = {
html.innerHTML = parsed.text
// heading...
parsed.style ?
- node.classList.add(parsed.style)
+ node.classList.add(...parsed.style)
: node.classList.remove(...this.__styles__)
} else {
html.innerHTML = data.text }
@@ -306,9 +269,10 @@ var Outline = {
return this },
// block serialization...
- // XXX STUB...
// XXX shouild we support headings + other formatting per block???
- // XXX these should be symetrical -- now one returns text the other an object...
+ // XXX split this up into a generic handler + plugins...
+ // XXX need a way to filter input text...
+ // use-case: hidden attributes...
__styles__: [
'heading-1',
'heading-2',
@@ -324,11 +288,13 @@ var Outline = {
}
var heading = function(level){
return function(_, text){
- elem.style = 'heading-'+level
+ elem.style ??= []
+ elem.style.push('heading-'+level)
return text } }
var style = function(style){
return function(_, text){
- elem.style = style
+ elem.style ??= []
+ elem.style.push(style)
return text } }
elem.text = code
// hidden attributes...
@@ -342,33 +308,37 @@ var Outline = {
// id...
.replace(/(\n|^)\s*id::\s*(.*)\s*(\n|$)/,
function(_, value){
- elem.collapsed = value.trim() == 'true'
+ elem.id = value.trim()
return '' })
// markdown...
- // ToDo...
- .replace(/^TODO\s*(.*)$/, ' $1')
- .replace(/^DONE\s*(.*)$/, ' $1')
// style: headings...
- .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*(.*)$/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+(.*)$/, style('list-item'))
- .replace(/^\s*(.*):\s*$/, style('list'))
+ .replace(/^[-\*]\s+(.*)$/m, style('list-item'))
+ .replace(/^\s*(.*):\s*$/m, style('list'))
// style: misc...
- .replace(/^((\/\/|;)\s+.*)$/, style('comment'))
- .replace(/^XXX\s+(.*)$/, style('XXX'))
- .replace(/^(.*)\s*XXX$/, style('XXX'))
+ .replace(/^((\/\/|;)\s+.*)$/m, style('comment'))
+ .replace(/^XXX\s+(.*)$/m, style('XXX'))
+ .replace(/^(.*)\s*XXX$/m, style('XXX'))
// basic styling...
// XXX these are quite naive...
- .replace(/\*(.*)\*/g, '$1')
- .replace(/~([^~]*)~/g, '$1')
- .replace(/_([^_]*)_/g, '$1')
+ .replace(/\*(.*)\*/gm, '$1')
+ .replace(/~([^~]*)~/gm, '$1')
+ .replace(/_([^_]*)_/gm, '$1')
// elements...
- .replace(/(\n|^)---*\h*(\n|$)/, '$1