diff --git a/experiments/outline-editor/editor.css b/experiments/outline-editor/editor.css index 7d7c397..4afeda0 100755 --- a/experiments/outline-editor/editor.css +++ b/experiments/outline-editor/editor.css @@ -29,7 +29,7 @@ /*text-size-adjust: none;*/ text-size-adjust: 150%; - /*scroll-behavior: smooth;*/ + } .editor { @@ -49,6 +49,9 @@ display: none; } +.editor .children { +} + .editor .outline { display: block; position: relative; @@ -60,19 +63,18 @@ padding-right: var(--outline-padding); } -.editor .outline [tabindex] { +.editor .outline .block { position: relative; outline: none; border: none; } -.editor .outline [tabindex] [tabindex] { +.editor .outline .block .block { margin-left: var(--item-indent); } -.editor .outline [tabindex]>span, -.editor .outline [tabindex]>textarea { +.editor .outline .block>.text { display: block; width: 100%; - /* XXX this is a tiny bit off and using textarea's height here is off too... */ + /* XXX this is a tiny bit off and using .code's height here is off too... */ min-height: calc(1em + var(--item-padding) * 2); padding-top: var(--item-padding); padding-bottom: var(--item-padding); @@ -89,60 +91,58 @@ border: none; } /* show/hide node's view/code... */ -/*.editor .outline [tabindex]>textarea:focus+span,*/ -.editor .outline [tabindex]>textarea:not(:focus) { +/*.editor .outline .block>.code:focus+.view,*/ +.editor .outline .block>.code:not(:focus) { position: absolute; opacity: 0; } -/* hide span content but show before/after -- keep bulets and touch zones... */ -.editor .outline [tabindex]>textarea:focus+span { +/* hide .view content but show before/after -- keep bulets and touch zones... */ +.editor .outline .block>.code:focus+.view { position: absolute; top: 0; visibility: hidden; } -.editor .outline [tabindex]>textarea:focus+span:before, -.editor .outline [tabindex]>textarea:focus+span:after { +.editor .outline .block>.code:focus+.view:before, +.editor .outline .block>.code:focus+.view:after { visibility: visible; } -/* click through the span text to the textarea */ -.editor .outline [tabindex]>span { +/* click through the .view text to the .code */ +.editor .outline .block>.view { position: relative; pointer-events: none; } /* block hover... */ -.editor .outline [tabindex]:hover>span { +.editor .outline .block:hover>.view { background: linear-gradient( 90deg, rgba(0,0,0,0.01) 0%, rgba(0,0,0,0.01) 80%, rgba(0,0,0,0.03) 100%); } -.editor .outline [tabindex]>span:blank { +.editor .outline .block>.view:blank { content: " "; } -.editor .outline [tabindex]>textarea { +.editor .outline .block>.code { height: calc(2 * var(--item-padding) + 1em); overflow: hidden; resize: none; } /* clickable things in view */ -.editor .outline [tabindex]>span a, -.editor .outline [tabindex]>span input { +.editor .outline .block>.view a, +.editor .outline .block>.view input { pointer-events: auto; } /* focus... */ -editor .outline [tabindex]:focus { +editor .outline .block:focus { /*outline: solid 0.2em silver;*/ outline: none; } -.editor .outline [tabindex]:focus>span, -.editor .outline [tabindex]:focus>textarea { +.editor .outline .block:focus>.text { background: rgba(0,0,0,0.1); } -.editor .outline [tabindex].focused:not(:focus)>span, -.editor .outline [tabindex].focused:not(:focus)>textarea { +.editor .outline .block.focused:not(:focus)>.text { background: rgba(0,0,0,0.01); } @@ -151,8 +151,8 @@ editor .outline [tabindex]:focus { } /* click/tap zones for expand button... */ -.editor .outline [tabindex]>span:before, -.editor .outline [tabindex]>span:after { +.editor .outline .block>.view:before, +.editor .outline .block>.view:after { --size: 3rem; content: ""; @@ -185,23 +185,23 @@ editor .outline [tabindex]:focus { background: transparent; } /* left indicator */ -.editor .outline [tabindex]>span:before { +.editor .outline .block>.view:before { justify-content: right; left: calc(-1 * var(--size)); } /* right indicator (collapse/expand) */ -.editor .outline [tabindex]>span:after { +.editor .outline .block>.view:after { color: silver; } -.editor .outline [tabindex]:has([tabindex])>span:after { +.editor .outline .block:has(.block)>.view:after { content: "○"; } -.editor .outline [tabindex][collapsed]>span:after { +.editor .outline .block[collapsed]>.view:after { content: "●"; } /* collapse -- hide children... */ -.editor .outline [tabindex][collapsed] [tabindex] { +.editor .outline .block[collapsed] .block { display: none; } @@ -242,58 +242,42 @@ editor .outline [tabindex]:focus { .editor .outline .heading-6 { margin-top: 1rem; } -.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 { +.editor .outline .heading-1>.text, +.editor .outline .heading-2>.text, +.editor .outline .heading-3>.text, +.editor .outline .heading-4>.text, +.editor .outline .heading-5>.text, +.editor .outline .heading-6>.text { 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 { +.editor .outline .heading-1>.text, +.editor .outline .heading-2>.text, +.editor .outline .heading-3>.text { border-bottom: solid 1px rgba(0,0,0,0.1); } -.editor .outline .heading-1>span, -.editor .outline .heading-1>textarea { +.editor .outline .heading-1>.text { --font-size: 2.5em; } -.editor .outline .heading-2>span, -.editor .outline .heading-2>textarea { +.editor .outline .heading-2>.text { --font-size: 1.9em; } -.editor .outline .heading-3>span, -.editor .outline .heading-3>textarea { +.editor .outline .heading-3>.text { --font-size: 1.5em; } -.editor .outline .heading-4>span, -.editor .outline .heading-4>textarea { +.editor .outline .heading-4>.text { --font-size: 1.3em; } -.editor .outline .heading-5>span, -.editor .outline .heading-5>textarea { +.editor .outline .heading-5>.text { --font-size: 1.1em; } -.editor .outline .heading-6>span, -.editor .outline .heading-6>textarea { +.editor .outline .heading-6>.text { --font-size: 1em; } /* Quote... */ -.editor .outline .quote>span, -.editor .outline .quote>textarea { +.editor .outline .quote>.text { --indent: 1rem; --margin: 0.7rem; --item-padding-ratio: 0.7; @@ -315,33 +299,66 @@ editor .outline [tabindex]:focus { /* List... */ -/* XXX needs to be in the middle of the first span but with universal size... */ -.editor .outline .list-item>span:before, -.editor .outline .list>[tabindex]>span:not(:empty):before { +/* XXX needs to be in the middle of the first .view but with universal size... */ +.editor .outline .list-item>.view:before, +.editor .outline .list>.children>.block>.view:not(:empty):before { content: "◼"; color: gray; } -.editor .outline .list>.list>[tabindex]>span:not(:empty):before { +.editor .outline + .list>.children + >.list>.children>.block>.view:not(:empty):before { content: "●"; } -.editor .outline .list>.list>.list>[tabindex]>span:not(:empty):before { +.editor .outline + .list>.children + >.list>.children + >.list>.children>.block>.view:not(:empty):before { content: "○"; } -.editor .outline .list>.list>.list>.list>[tabindex]>span:not(:empty):before { +.editor .outline + .list>.children + >.list>.children + >.list>.children + >.list>.children>.block>.view:not(:empty):before { content: "▪"; } /* List... */ /* XXX nested lists are broken -- seems that I need a container for the children... */ -.editor .outline .numbered-list { +.editor .outline .numbered-list>.children { counter-reset: numbered-list; } -.editor .outline .numbered-list>[tabindex]>span:not(:empty):before { +.editor .outline .numbered-list>.children>.block>.view:not(:empty):before { counter-increment: numbered-list; content: counter(numbered-list) "."; color: gray; } +.editor .outline + .numbered-list>.children + >.numbered-list>.children>.block>.view:not(:empty):before { + counter-increment: numbered-list; + content: counter(numbered-list, lower-alpha) "."; + color: gray; +} +.editor .outline + .numbered-list>.children + >.numbered-list>.children + >.numbered-list>.children>.block>.view:not(:empty):before { + counter-increment: numbered-list; + content: counter(numbered-list, lower-roman) "."; + color: gray; +} +.editor .outline + .numbered-list>.children + >.numbered-list>.children + >.numbered-list>.children + >.numbered-list>.children>.block>.view:not(:empty):before { + counter-increment: numbered-list; + content: counters(numbered-list, ".") "."; + color: gray; +} /* Notes... */ @@ -356,20 +373,20 @@ editor .outline [tabindex]:focus { background: rgba(0,0,0,0.05); } /* XXX this prevents it from being accesible via click/tap... */ -.editor .outline .NOTE>span:empty { +.editor .outline .NOTE>.view:empty { display: none; } -.editor .outline .NOTE>span:empty ~ [tabindex] { +.editor .outline .NOTE>.view:empty ~ .block { /* XXX calculate this... */ margin-left: 1em; } -.editor .outline .NOTE>span:before { +.editor .outline .NOTE>.view:before { content: "" !important; } /* correct the right click zone... */ /* XXX need to account for nesting... (???) */ -.editor .outline [tabindex].NOTE>span:after, -.editor .outline [tabindex].NOTE [tabindex]>span:after { +.editor .outline .block.NOTE>.view:after, +.editor .outline .block.NOTE .block>.view:after { margin-right: calc(-1 * var(--padding-h)); } @@ -379,7 +396,7 @@ editor .outline [tabindex]:focus { font-weight: bold; background: yellow; } -.editor .outline .XXX>span { +.editor .outline .XXX>.view { background: yellow; } @@ -388,13 +405,13 @@ editor .outline [tabindex]:focus { .editor.hide-comments .outline .comment { display: none; } -.editor .outline .comment>span { +.editor .outline .comment>.view { color: silver; } /* Checkboxes... */ -.editor .outline [tabindex].todo>span { +.editor .outline .block.todo>.view { width: calc( 100% - var(--checkbox-size) @@ -403,8 +420,8 @@ editor .outline [tabindex]:focus { var(--checkbox-size) + var(--checkbox-margin)); } -.editor .outline [tabindex].check>span input[type=checkbox], -.editor .outline [tabindex].todo>span input[type=checkbox] { +.editor .outline .block.check>.view input[type=checkbox], +.editor .outline .block.todo>.view input[type=checkbox] { height: var(--checkbox-size); width: var(--checkbox-size); @@ -417,13 +434,13 @@ editor .outline [tabindex]:focus { /* NOTE: this appears to be needed for the em sizes above to work correctly */ font-size: 1em; } -.editor .outline [tabindex].todo>span input[type=checkbox]:first-child { +.editor .outline .block.todo>.view input[type=checkbox]:first-child { margin-left: calc( -1 * var(--checkbox-size) - var(--checkbox-margin)); } /* correct the left click zone... */ -.editor .outline [tabindex].todo>span:before { +.editor .outline .block.todo>.view:before { margin-left: calc( -1 * var(--checkbox-size) - var(--checkbox-margin)); @@ -431,7 +448,7 @@ editor .outline [tabindex]:focus { /* code... */ -.editor .outline [tabindex]>span code { +.editor .outline .block>.view code { padding: 0.1em 0.3em; font-family: monospace; background: rgba(0,0,0,0.07); @@ -440,19 +457,19 @@ editor .outline [tabindex]:focus { /* Tables... */ -.editor .outline [tabindex]>span>table { +.editor .outline .block>.view>table { width: 100%; border-collapse: collapse; } -.editor .outline [tabindex]>span>table tr:nth-child(odd) { +.editor .outline .block>.view>table tr:nth-child(odd) { background: rgba(0,0,0,0.03); } -.editor .outline [tabindex]>span>table tr:first-child { +.editor .outline .block>.view>table tr:first-child { font-weight: bold; border-bottom: solid 0.1rem silver; background: transparent; } -.editor .outline [tabindex]>span>table td { +.editor .outline .block>.view>table td { height: calc(1em + var(--item-padding) * 2); padding: 0 1em; /*text-align: center;*/ @@ -461,13 +478,13 @@ editor .outline [tabindex]:focus { /********************************************************* Testing ***/ -.editor.show-click-zones .outline [tabindex]>span:before, -.editor.show-click-zones .outline [tabindex]>span:after { +.editor.show-click-zones .outline .block>.view:before, +.editor.show-click-zones .outline .block>.view: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 { +.editor.show-click-zones .outline .block:hover>.view:before, +.editor.show-click-zones .outline .block:hover>.view:after { background: rgba(0,0,0,0.1); } diff --git a/experiments/outline-editor/editor.js b/experiments/outline-editor/editor.js index a323b1f..cb841a6 100755 --- a/experiments/outline-editor/editor.js +++ b/experiments/outline-editor/editor.js @@ -82,6 +82,111 @@ var Outline = { // // XXX add support for node ID... // XXX need to be able to get the next elem on same level... + get: function(node='focused', offset){ + var that = this + offset = + offset == 'next' ? + 1 + : offset == 'prev' ? + -1 + : offset + var outline = this.outline + + // root nodes... + if(node == 'top'){ + return [...outline.children] } + // groups defaulting to .outline as base... + if(['all', 'visible', 'editable', 'selected'].includes(node)){ + return this.get(outline, node) } + // groups defaulting to .focused as base... + if(['parent', 'next', 'prev', 'children', 'siblings'].includes(node)){ + return this.get('focused', node) } + + // helpers... + var parent = function(node){ + return node === outline ? + node + : node?.parentElement?.parentElement } + var children = function(node){ + return node === outline ? + [...node.children] + : [...node?.lastChild?.children] } + + // single base node... + var edited + ;[node, edited] = + typeof(node) == 'number' ? + [this.get('visible').at(node), + edited] + : (node == 'outline' || node == 'root') ? + [outline, edited] + : node == 'focused' ? + [outline.querySelector(`.block:focus`) + || outline.querySelector(`.code:focus`) + || outline.querySelector('.block.focused'), + edited] + : node == 'edited' ? + [outline.querySelector(`.code:focus`), + outline.querySelector(`.code:focus`)] + : [node , edited] + + // get the .block... + if(node instanceof HTMLElement){ + while(node !== outline + && !node.classList.contains('block')){ + node = node.parentElement } } + + // no reference node... + if(node == null + || typeof(node) == 'string'){ + return undefined } + + // parent... + if(offset == 'parent'){ + return edited ? + parent(node).querySelector('.code') + : parent(node) } + + // node groups... + var nodes = + typeof(offset) == 'number' ? + this.get('visible') + : offset == 'all' ? + [...node.querySelectorAll('.block')] + : offset == 'visible' ? + [...node.querySelectorAll('.block')] + .filter(function(e){ + return e.offsetParent != null }) + : offset == 'editable' ? + [...node.querySelectorAll('.block>.code')] + : offset == 'selected' ? + [...node.querySelectorAll('.block[selected]')] + .filter(function(e){ + return e.offsetParent != null }) + : offset == 'children' ? + children(node) + : offset == 'siblings' ? + children(parent(node)) + : undefined + + // get node by offset... + if(typeof(offset) == 'number'){ + node = nodes.at(nodes.indexOf(node) + offset) + ?? nodes[0] + edited = edited ? + node.querySelector('.code') + : edited + nodes = undefined } + + return nodes !== undefined ? + edited ? + nodes + .map(function(){ + return node.querySelector('.code') }) + : nodes + : (edited + ?? node) }, + /*/ get: function(node='focused', offset){ var that = this @@ -93,10 +198,15 @@ var Outline = { var outline = this.outline + var parent = function(node){ + return node?.parentElement?.parentElement } + var children = function(node){ + return [...node?.lastChild?.children] } + // get parent node... if(node instanceof HTMLElement){ - while(!node.getAttribute('tabindex')){ - node = node.parentElement + while(!node.classList.contains('block')){ + node = node.parentElement if(node === this.outline){ return undefined } } } @@ -104,15 +214,15 @@ var Outline = { var NO_NODES = {} var nodes = node == 'all' ? - [...outline.querySelectorAll('[tabindex]')] + [...outline.querySelectorAll('.block')] : node == 'visible' ? - [...outline.querySelectorAll('[tabindex]')] + [...outline.querySelectorAll('.block')] .filter(function(e){ return e.offsetParent != null }) : node == 'editable' ? - [...outline.querySelectorAll('[tabindex]>textarea')] + [...outline.querySelectorAll('.block>textarea')] : node == 'selected' ? - [...outline.querySelectorAll('[tabindex][selected]')] + [...outline.querySelectorAll('.block[selected]')] : node == 'top' ? [...outline.children] .filter(function(elem){ @@ -136,11 +246,11 @@ var Outline = { typeof(node) == 'number' ? this.at(node) : node == 'focused' ? - (outline.querySelector(`[tabindex]:focus`) + (outline.querySelector(`.block:focus`) || outline.querySelector(`textarea:focus`)?.parentElement - || outline.querySelector('[tabindex].focused')) + || outline.querySelector('.block.focused')) : node == 'parent' ? - this.get('focused')?.parentElement + parent(this.get('focused')) : node var edited if(node == 'edited'){ @@ -152,15 +262,11 @@ var Outline = { // children... if(offset == 'children'){ - return [...node.children] - .filter(function(elem){ - return elem.getAttribute('tabindex') != null }) } + return children(node) } // siblings... if(offset == 'siblings'){ - return [...node.parentElement.children] - .filter(function(elem){ - return elem.getAttribute('tabindex') != null }) } + return children(parent(node)) } // offset... offset = @@ -177,9 +283,10 @@ var Outline = { : i % nodes.length node = nodes[i] edited = edited - && node.querySelector('textarea') } + && node.querySelector('.code') } return edited || node }, + //*/ at: function(index, nodes='visible'){ return this.get(nodes).at(index) }, focus: function(node='focused', offset){ @@ -229,20 +336,30 @@ var Outline = { var siblings = this.get(node, 'siblings') // deindent... if(!indent){ - var parent = cur.parentElement + var parent = this.get(node, 'parent') if(!parent.classList.contains('.outline')){ - var children = siblings.slice(siblings.indexOf(cur)+1) + var children = siblings + .slice(siblings.indexOf(cur)+1) parent.after(cur) children.length > 0 - && cur.append(...children) } + && cur.lastChild.append(...children) } // indent... } else { var parent = siblings[siblings.indexOf(cur) - 1] if(parent){ - parent.append(cur) } } + parent.lastChild.append(cur) } } return cur }, deindent: function(node='focused', indent=false){ return this.indent(node, indent) }, + show: function(node='focused', offset){ + var node = this.get(...arguments) + var outline = this.outline + var parent = node + do{ + parent = parent.parentElement + parent.removeAttribute('collapsed') + } while(parent !== outline) + return node }, toggleCollapse: function(node='focused', state='next'){ var that = this if(node == 'all'){ @@ -256,7 +373,7 @@ var Outline = { node = this.get(node) if(!node // only nodes with children can be collapsed... - || !node.querySelector('[tabindex]')){ + || !node.querySelector('.block')){ return } state = state == 'next' ? node.getAttribute('collapsed') != '' @@ -417,12 +534,9 @@ var Outline = { json: function(node){ var that = this node ??= this.outline - return [...node.children] + return [...node.lastChild.children] .map(function(elem){ - return elem.nodeName != 'DIV' ? - [] - : [that.data(elem)] }) - .flat() }, + return that.data(elem) }) }, // XXX add option to customize indent size... text: function(node, indent, level){ // .text(, ) @@ -489,16 +603,29 @@ var Outline = { // XXX should this handle children??? // XXX revise name... Block: function(data={}, place=null){ + var that = this if(typeof(data) != 'object'){ place = data data = {} } + + // block... var block = document.createElement('div') + block.classList.add('block') block.setAttribute('tabindex', '0') - var text = document.createElement('textarea') + // code... + var code = document.createElement('textarea') .autoUpdateSize() + code.classList.add('code', 'text') + // view... var html = document.createElement('span') - block.append(text, html) + html.classList.add('view', 'text') + // children... + var children = document.createElement('div') + children.classList.add('children') + children.setAttribute('tabindex', '-1') + block.append(code, html, children) this.update(block, data) + // place... var cur = this.get() if(place && cur){ @@ -506,7 +633,7 @@ var Outline = { 'before' : place ;(place == 'next' - && (cur.querySelector('[tabindex]') + && (cur.querySelector('.block') || cur.nextElementSibling)) ? this.get(place).before(block) : (place == 'next' @@ -527,7 +654,8 @@ var Outline = { .map(function(data){ var elem = that.Block(data) if((data.children || []).length > 0){ - elem.append(...level(data.children)) } + elem.lastChild + .append(...level(data.children)) } return elem }) } this .clear() @@ -616,19 +744,19 @@ var Outline = { return } if(this.right_key_expands){ this.toggleCollapse(false) - var child = this.focus('children')[0] - if(!child){ - this.focus('next') } + this.focus('next') } else { evt.shiftKey ? this.toggleCollapse(false) - : this.get('children')[0]?.focus() } }, + : this.focus('next') } }, // indent... Tab: function(evt){ evt.preventDefault() var edited = this.get('edited') - var node = this.indent(!evt.shiftKey) + var node = this.show( + this.indent(!evt.shiftKey)) + // keep focus in node... ;(edited ? edited : node)?.focus() }, @@ -698,8 +826,11 @@ var Outline = { function(evt){ var elem = evt.target + if(elem.classList.contains('children')){ + return } + // expand/collapse - if(elem.nodeName == 'SPAN' + if(elem.classList.contains('view') && elem.parentElement.getAttribute('tabindex')){ // click: left of elem (outside) if(evt.offsetX < 0){ @@ -718,12 +849,12 @@ var Outline = { // NOTE: this is usefull if element text is hidden but the // frame is still visible... if(elem.getAttribute('tabindex')){ - elem.querySelector('textarea').focus() } + elem.querySelector('.code').focus() } // toggle checkbox... if(elem.type == 'checkbox'){ var node = that.get(elem) - var text = node.querySelector('textarea') + var text = node.querySelector('.code') // get the checkbox order... var i = [...node.querySelectorAll('input[type=checkbox]')].indexOf(elem) var to = elem.checked ? @@ -749,25 +880,27 @@ var Outline = { // toggle view/code of nodes... outline.addEventListener('focusin', function(evt){ - var node = evt.target - // scroll... - // XXX a bit odd still and not smooth... - ;((node.nodeName == 'SPAN' - || node.nodeName == 'TEXTAREA') ? - node - : node.querySelector('textarea+span')) - ?.scrollIntoView({ - block: 'nearest', - behavior: 'smooth', - }) + var elem = evt.target + + if(elem.classList.contains('children')){ + return } + // handle focus... for(var e of [...that.dom.querySelectorAll('.focused')]){ e.classList.remove('focused') } that.get('focused')?.classList?.add('focused') // textarea... - if(node.nodeName == 'TEXTAREA' - && node?.nextElementSibling?.nodeName == 'SPAN'){ - node.updateSize() } }) + if(elem.classList.contains('code')){ + elem.updateSize() } + + /*/ scroll... + that.get(node).querySelector('view') + ?.scrollIntoView({ + block: 'nearest', + behavior: 'smooth', + }) + //*/ + }) outline.addEventListener('focusout', function(evt){ var node = evt.target @@ -809,9 +942,11 @@ var Outline = { // code... var code = this.code if(code){ + var t = Date.now() this.load(code.innerHTML .replace(/</g, '<') - .replace(/>/g, '>')) } + .replace(/>/g, '>')) + console.log(`Parse: ${Date.now() - t}ms`)} return this }, } diff --git a/experiments/outline-editor/index.html b/experiments/outline-editor/index.html index 9164a99..d777a3e 100755 --- a/experiments/outline-editor/index.html +++ b/experiments/outline-editor/index.html @@ -36,7 +36,6 @@ var setup = function(){ - Bonsai - - ## ToDo: - - BUG? odd/random focus jumps on refocusing page (can't reporduce yet) - BUG? pressing down from a longer line will jump over a shorter line - here is the line to jump from, for example from here an we'll not get here... @@ -100,13 +99,29 @@ var setup = function(){ - Text - Lists:: - bullet: - - a + - a: + collapsed:: true + - bullets: + - in: + - very: + - deep: + - list: + - of: + - items: - b - c - numbered# - a - b# - - x + - x# + collapsed:: true + - bullets# + - in# + - very# + - deep# + - list# + - of# + - items# - y - z - c