mirror of
				https://github.com/flynx/pWiki.git
				synced 2025-10-31 19:10:08 +00:00 
			
		
		
		
	lots of fixes + started major refactoring...
Signed-off-by: Alex A. Naanou <alex.nanou@gmail.com>
This commit is contained in:
		
							parent
							
								
									53ad572369
								
							
						
					
					
						commit
						4690bc0770
					
				| @ -54,13 +54,23 @@ | ||||
| 	display: block; | ||||
| 	position: relative; | ||||
| 
 | ||||
| 	/* XXX do a better calculation... */ | ||||
| 	width: calc(100% - var(--button-size) - var(--outline-padding) * 2); | ||||
| 
 | ||||
| 	padding-left: var(--outline-padding); | ||||
| 	padding-right: var(--outline-padding); | ||||
| 	padding: 1em var(--outline-padding); | ||||
| 	padding-bottom: 1.2em | ||||
| } | ||||
| 
 | ||||
| /* virtual empty block... */ | ||||
| .editor .outline:empty:after { | ||||
| 	content: "Empty"; | ||||
| 	display: block; | ||||
| 	font-style: italic; | ||||
| 	color: rgba(0,0,0,0.2); | ||||
| } | ||||
| .editor .outline:empty:hover:after { | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| .editor .outline .block { | ||||
| 	position: relative; | ||||
| 	outline: none; | ||||
| @ -110,6 +120,7 @@ | ||||
| 	pointer-events: none; | ||||
| } | ||||
| /* block hover... */ | ||||
| .editor .outline:empty:hover:after, | ||||
| .editor .outline .block:hover>.view { | ||||
| 	background: linear-gradient( | ||||
| 		90deg,  | ||||
| @ -127,6 +138,7 @@ | ||||
| } | ||||
| /* clickable things in view */ | ||||
| .editor .outline .block>.view a, | ||||
| .editor .outline .block>.view pre, | ||||
| .editor .outline .block>.view input { | ||||
| 	pointer-events: auto; | ||||
| } | ||||
| @ -138,7 +150,7 @@ editor .outline .block:focus { | ||||
| 	outline: none; | ||||
| } | ||||
| .editor .outline .block:focus>.text { | ||||
| 	background: rgba(0,0,0,0.1); | ||||
| 	background: rgba(0,0,0,0.07); | ||||
| } | ||||
| .editor .outline .block.focused:not(:focus)>.text { | ||||
| 	background: rgba(0,0,0,0.01); | ||||
| @ -464,11 +476,13 @@ editor .outline .block:focus { | ||||
| 	font-family: monospace; | ||||
| 	background: rgba(0,0,0,0.07); | ||||
| 	border-radius: 0.2em; | ||||
| 	outline: none; | ||||
| } | ||||
| .editor .outline .block>.view pre>code { | ||||
| 	display: block; | ||||
| 	padding: 0.6em 0.6em; | ||||
| 	padding-bottom: 0.8em; | ||||
| 	outline: none; | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
|  | ||||
| @ -25,6 +25,56 @@ var atLine = function(elem, index){ | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| //---------------------------------------------------------------------
 | ||||
| 
 | ||||
| var codeBlock = { | ||||
| 	// can be used in:
 | ||||
| 	// 		<string>.replace(codeBlock.pattern, codeBlock.handler)
 | ||||
| 	// or:
 | ||||
| 	// 		codeBlock
 | ||||
| 	pattern: /(?<!\\)```(.*\s*\n)((\n|.)*?)\h*(?<!\\)```/g, | ||||
| 	handler: function(_, language, code){ | ||||
| 		var quote = this?.quote  | ||||
| 			|| codeBlock.quote | ||||
| 		language = language.trim() | ||||
| 		language = language ? | ||||
| 			'language-'+language | ||||
| 			: language | ||||
| 		return `<pre>` | ||||
| 				+`<code contenteditable="true" class="${language}">${  | ||||
| 					quote ? | ||||
| 						quote(code) | ||||
| 						: code | ||||
| 				}</code>` | ||||
| 			+`</pre>` }, | ||||
| 
 | ||||
| 	quote: function(text){ | ||||
| 		return text | ||||
| 			.replace(/(?<!\\)&/g, '&') | ||||
| 			.replace(/(?<!\\)</g, '<') | ||||
| 			.replace(/(?<!\\)>/g, '>') | ||||
| 			.replace(/\\(?!`)/g, '\\\\') }, | ||||
| 
 | ||||
| 	map: function(text, func){ | ||||
| 		return text.replace(this.pattern, func) }, | ||||
| 
 | ||||
| 	replace: function(text, index, updated){ | ||||
| 		return this.map(text,  | ||||
| 			function(match, language, code){ | ||||
| 				return index-- != 0 ? | ||||
| 					match | ||||
| 					: ('```'+language | ||||
| 						+ (typeof(updated) == 'function' ? | ||||
| 							updated(code) | ||||
| 							: updated) | ||||
| 						+'```') }) }, | ||||
| 
 | ||||
| 	toHTML: function(text){ | ||||
| 		return this.map(text, this.handler) }, | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| //---------------------------------------------------------------------
 | ||||
| 
 | ||||
| // XXX experiment with a concatinative model...
 | ||||
| @ -101,12 +151,13 @@ var Outline = { | ||||
| 		// 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 } | ||||
| 					outline | ||||
| 				: node.parentElement === outline ? | ||||
| 					outline | ||||
| 				: node.parentElement.parentElement } | ||||
| 		var children = function(node){ | ||||
| 			return node === outline ? | ||||
| 				[...node.children] | ||||
| @ -337,11 +388,6 @@ var Outline = { | ||||
| 				.replace(/\\(?!`)/g, '\\\\') } | ||||
| 		var quote = function(_, code){ | ||||
| 			return `<code>${quoteText(code)}</code>` } | ||||
| 		var pre = function(_, language, code){ | ||||
| 			language = language ? | ||||
| 				'language-'+language | ||||
| 				: language | ||||
| 			return `<pre><code class="${language}">${ quoteText(code) }</code></pre>` } | ||||
| 		var table = function(_, body){ | ||||
| 			return `<table><tr><td>${ | ||||
| 				body | ||||
| @ -349,78 +395,123 @@ var Outline = { | ||||
| 					.replace(/\s*\|\s*/gm, '</td><td>') | ||||
| 			}</td></td></table>` } | ||||
| 
 | ||||
| 		elem.text = code  | ||||
| 			// hidden attributes...
 | ||||
| 			// XXX make this generic...
 | ||||
| 			// collapsed...
 | ||||
| 			.replace(/(\n|^)\s*collapsed::\s*(.*)\s*(\n|$)/,  | ||||
| 				function(_, value){ | ||||
| 					elem.collapsed = value.trim() == 'true' | ||||
| 					return '' }) | ||||
| 			// id...
 | ||||
| 			.replace(/(\n|^)\s*id::\s*(.*)\s*(\n|$)/,  | ||||
| 				function(_, value){ | ||||
| 					elem.id = value.trim() | ||||
| 					return '' }) | ||||
| 			// markdown...
 | ||||
| 			// style: headings...
 | ||||
| 			.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+(.*)$/m, style('list-item'))
 | ||||
| 			.replace(/^\s*(.*)(?<!\\):\s*$/m, style('list')) | ||||
| 			.replace(/^\s*(.*)(?<!\\)#\s*$/m, style('numbered-list')) | ||||
| 			// style: misc...
 | ||||
| 			.replace(/^\s*(?<!\\)>\s+(.*)$/m, style('quote')) | ||||
| 			.replace(/^\s*(?<!\\)((\/\/|;)\s+.*)$/m, style('comment')) | ||||
| 			.replace(/^\s*(?<!\\)NOTE:?\s*(.*)$/m, style('NOTE')) | ||||
| 			.replace(/^\s*(?<!\\)XXX\s+(.*)$/m, style('XXX')) | ||||
| 			.replace(/^(.*)\s*(?<!\\)XXX$/m, style('XXX')) | ||||
| 			.replace(/(\s*)(?<!\\)(ASAP|BUG|FIX|HACK|STUB|WARNING|CAUTION)(\s*)/gm,  | ||||
| 				'$1<span class="highlight $2">$2</span>$3') | ||||
| 			// elements...
 | ||||
| 			.replace(/(\n|^)(?<!\\)---*\h*(\n|$)/m, '$1<hr>') | ||||
| 			// ToDo...
 | ||||
| 			// NOTE: these are separate as we need to align block text 
 | ||||
| 			// 		to leading chekbox...
 | ||||
| 			.replace(/^\s*(?<!\\)\[[_ ]\]\s*/m,  | ||||
| 				style('todo', '<input type="checkbox">')) | ||||
| 			.replace(/^\s*(?<!\\)\[[Xx]\]\s*/m,  | ||||
| 				style('todo', '<input type="checkbox" checked>')) | ||||
| 			// inline checkboxes...
 | ||||
| 			.replace(/\s*(?<!\\)\[[_ ]\]\s*/gm,  | ||||
| 				style('check', '<input type="checkbox">')) | ||||
| 			.replace(/\s*(?<!\\)\[[Xx]\]\s*/gm,  | ||||
| 				style('check', '<input type="checkbox" checked>')) | ||||
| 			// tables...
 | ||||
| 			.replace(/^\s*(?<!\\)\|\s*((.|\n)*)\s*\|\s*$/, table) | ||||
| 			// basic styling...
 | ||||
| 			// XXX revise...
 | ||||
| 			.replace(/(?<!\\)\*(?=[^\s*])(([^*]|\\\*)*[^\s*])(?<!\\)\*/gm, '<b>$1</b>') | ||||
| 			.replace(/(?<!\\)~(?=[^\s~])(([^~]|\\~)*[^\s~])(?<!\\)~/gm, '<s>$1</s>') | ||||
| 			.replace(/(?<!\\)_(?=[^\s_])(([^_]|\\_)*[^\s_])(?<!\\)_/gm, '<i>$1</i>')  | ||||
| 		    // code/quoting...
 | ||||
| 			.replace(/(?<!\\)```(.*)\s*\n((\n|.)*)\h*(?<!\\)```\s*/g, pre)  | ||||
| 			.replace(/(?<!\\)`(?=[^\s])(([^`]|\\`)*[^\s])(?<!\\)`/gm, quote)  | ||||
| 			// XXX support "\==" in mark...
 | ||||
| 			.replace(/(?<!\\)==(?=[^\s])(.*[^\s])(?<!\\)==/gm, '<mark>$1</mark>')  | ||||
| 			// links...
 | ||||
| 			.replace(/(?<!\\)\[([^\]]*)\]\(([^)]*)\)/g, '<a href="$2">$1</a>') | ||||
| 			.replace(/((?:https?:|ftps?:)[^\s]*)(\s*)/g, '<a href="$1">$1</a>$2') | ||||
| 			// characters...
 | ||||
| 			// XXX use ligatures for these???
 | ||||
| 			.replace(/(?<!\\)\(i\)/gm, '🛈')  | ||||
| 			.replace(/(?<!\\)\(c\)/gm, '©')  | ||||
| 			.replace(/(?<!\\)\/!\\/gm, '⚠')  | ||||
| 			.replace(/(?<!\\)---(?!-)/gm, '—')  | ||||
| 			.replace(/(?<!\\)--(?!-)/gm, '–')  | ||||
| 			// quoting...
 | ||||
| 			// NOTE: this must be last...
 | ||||
| 			.replace(/(?<!\\)\\(.)/gm, '$1')  | ||||
| 		var preParse = function(text){ | ||||
| 			return text  | ||||
| 				// hidden attributes...
 | ||||
| 				// XXX make this generic...
 | ||||
| 				// collapsed...
 | ||||
| 				.replace(/(\n|^)\s*collapsed::\s*(.*)\s*(\n|$)/,  | ||||
| 					function(_, value){ | ||||
| 						elem.collapsed = value.trim() == 'true' | ||||
| 						return '' }) | ||||
| 				// id...
 | ||||
| 				.replace(/(\n|^)\s*id::\s*(.*)\s*(\n|$)/,  | ||||
| 					function(_, value){ | ||||
| 						elem.id = value.trim() | ||||
| 						return '' }) } | ||||
| 		var blockParse = function(text){ | ||||
| 			return text  | ||||
| 				// markdown...
 | ||||
| 				// style: headings...
 | ||||
| 				.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+(.*)$/m, style('list-item'))
 | ||||
| 				.replace(/^\s*(.*)(?<!\\):\s*$/m, style('list')) | ||||
| 				.replace(/^\s*(.*)(?<!\\)#\s*$/m, style('numbered-list')) | ||||
| 
 | ||||
| 				// style: misc...
 | ||||
| 				.replace(/^\s*(?<!\\)>\s+(.*)$/m, style('quote')) | ||||
| 				.replace(/^\s*(?<!\\)((\/\/|;)\s+.*)$/m, style('comment')) | ||||
| 				.replace(/^\s*(?<!\\)NOTE:?\s*(.*)$/m, style('NOTE')) | ||||
| 				.replace(/^\s*(?<!\\)XXX\s+(.*)$/m, style('XXX')) | ||||
| 				.replace(/^(.*)\s*(?<!\\)XXX$/m, style('XXX')) } | ||||
| 		var quoteParse = function(text){ | ||||
| 			return text | ||||
| 				.replace(codeBlock.pattern, codeBlock.handler) | ||||
| 				.replace(/(?<!\\)`(?=[^\s])(([^`]|\\`)*[^\s])(?<!\\)`/gm, quote) } | ||||
| 		var inlineParse = function(text){ | ||||
| 			return text  | ||||
| 				.replace(/(\s*)(?<!\\)(FEATURE:|Q:|Question:|Note:)(\s*)/gm,  | ||||
| 					'$1<b class="$2">$2</b>$3') | ||||
| 				.replace(/(\s*)(?<!\\)(ASAP|BUG|FIX|HACK|STUB|WARNING|CAUTION)(\s*)/gm,  | ||||
| 					'$1<span class="highlight $2">$2</span>$3') | ||||
| 				// elements...
 | ||||
| 				.replace(/(\n|^)(?<!\\)---*\h*(\n|$)/m, '$1<hr>') | ||||
| 				// ToDo...
 | ||||
| 				// NOTE: these are separate as we need to align block text 
 | ||||
| 				// 		to leading chekbox...
 | ||||
| 				.replace(/^\s*(?<!\\)\[[_ ]\]\s*/m,  | ||||
| 					style('todo', '<input type="checkbox">')) | ||||
| 				.replace(/^\s*(?<!\\)\[[Xx]\]\s*/m,  | ||||
| 					style('todo', '<input type="checkbox" checked>')) | ||||
| 				// inline checkboxes...
 | ||||
| 				.replace(/\s*(?<!\\)\[[_ ]\]\s*/gm,  | ||||
| 					style('check', '<input type="checkbox">')) | ||||
| 				.replace(/\s*(?<!\\)\[[Xx]\]\s*/gm,  | ||||
| 					style('check', '<input type="checkbox" checked>')) | ||||
| 				// tables...
 | ||||
| 				.replace(/^\s*(?<!\\)\|\s*((.|\n)*)\s*\|\s*$/, table) | ||||
| 				// basic styling...
 | ||||
| 				// XXX revise...
 | ||||
| 				.replace(/(?<!\\)\*(?=[^\s*])(([^*]|\\\*)*[^\s*])(?<!\\)\*/gm, '<b>$1</b>') | ||||
| 				.replace(/(?<!\\)~(?=[^\s~])(([^~]|\\~)*[^\s~])(?<!\\)~/gm, '<s>$1</s>') | ||||
| 				.replace(/(?<!\\)_(?=[^\s_])(([^_]|\\_)*[^\s_])(?<!\\)_/gm, '<i>$1</i>')  | ||||
| 				// code/quoting...
 | ||||
| 				//.replace(/(?<!\\)`(?=[^\s])(([^`]|\\`)*[^\s])(?<!\\)`/gm, quote) 
 | ||||
| 				// XXX support "\==" in mark...
 | ||||
| 				.replace(/(?<!\\)==(?=[^\s])(.*[^\s])(?<!\\)==/gm, '<mark>$1</mark>')  | ||||
| 				// links...
 | ||||
| 				.replace(/(?<!\\)\[([^\]]*)\]\(([^)]*)\)/g, '<a href="$2">$1</a>') | ||||
| 				.replace(/((?:https?:|ftps?:)[^\s]*)(\s*)/g, '<a href="$1">$1</a>$2') | ||||
| 				// characters...
 | ||||
| 				// XXX use ligatures for these???
 | ||||
| 				.replace(/(?<!\\)\(i\)/gm, '🛈')  | ||||
| 				.replace(/(?<!\\)\(c\)/gm, '©')  | ||||
| 				.replace(/(?<!\\)\/!\\/gm, '⚠')  | ||||
| 				.replace(/(?<!\\)---(?!-)/gm, '—')  | ||||
| 				.replace(/(?<!\\)--(?!-)/gm, '–') } | ||||
| 		var postParse = function(text){ | ||||
| 			return text | ||||
| 				// quoting...
 | ||||
| 				// NOTE: this must be last...
 | ||||
| 				.replace(/(?<!\\)\\(.)/gm, '$1') } | ||||
| 
 | ||||
| 		var parse = function(text){ | ||||
| 			// split text into parsable and non-parsable sections...
 | ||||
| 			// split fomat:
 | ||||
| 			// 	[ text <match> <type> <body>, ... ]
 | ||||
| 			var pattern = /(<(pre|code)(?:|\s[^>]*)>((?:\n|.)*)<\/\2>)/g | ||||
| 			var sections =  | ||||
| 				quoteParse( | ||||
| 						blockParse( | ||||
| 							preParse(text | ||||
| 								.replace(/\x00/g, '')))) | ||||
| 					.split(pattern) | ||||
| 			// sort out the sections...
 | ||||
| 			var parsable = []  | ||||
| 			var quoted = [] | ||||
| 			while(sections.length > 0){ | ||||
| 				var [section, match] = sections.splice(0, 4) | ||||
| 				parsable.push(section) | ||||
| 				quoted.push(match) } | ||||
| 			// parse only the parsable sections...
 | ||||
| 			return postParse( | ||||
| 				inlineParse( | ||||
| 						parsable | ||||
| 							.join('\x00')) | ||||
| 					.split(/\x00/g) | ||||
| 					.map(function(section){ | ||||
| 						return [section, quoted.shift() ?? '']	}) | ||||
| 					.flat() | ||||
| 					.join('')) } | ||||
| 
 | ||||
| 		elem.text = parse(code) | ||||
| 
 | ||||
| 		return elem }, | ||||
| 	// XXX essentially here we need to remove service stuff like some 
 | ||||
| 	// 		attributes (collapsed, id, ...)...
 | ||||
| @ -482,7 +573,7 @@ var Outline = { | ||||
| 		text = text | ||||
| 			.replace(/^\s*\n/, '') | ||||
| 		text = ('\n' + text) | ||||
| 			.split(/\n(\s*)- /g) | ||||
| 			.split(/\n(\s*)(?:- |-\s*$)/gm) | ||||
| 			.slice(1) | ||||
| 		var tab = ' '.repeat(this.tab_size || 8) | ||||
| 		var level = function(lst, prev_sep=undefined, parent=[]){ | ||||
| @ -747,6 +838,15 @@ var Outline = { | ||||
| 				if(elem.classList.contains('children')){ | ||||
| 					return } | ||||
| 
 | ||||
| 				// empty outline -> create new eleemnt...
 | ||||
| 				if(elem.classList.contains('outline') | ||||
| 						&& elem.children.length == 0){ | ||||
| 					// create new eleemnt and edit it...
 | ||||
| 					var block = that.Block() | ||||
| 					that.outline.append(block) | ||||
| 					that.edit(block) | ||||
| 					return } | ||||
| 
 | ||||
| 				// expand/collapse
 | ||||
| 				if(elem.classList.contains('view') | ||||
| 						&& elem.parentElement.getAttribute('tabindex')){ | ||||
| @ -783,10 +883,14 @@ var Outline = { | ||||
| 							to | ||||
| 							: m } | ||||
| 					text.value = text.value.replace(/\[[Xx_]\]/g, toggle) } }) | ||||
| 		// heboard handling...
 | ||||
| 		// keyboard handling...
 | ||||
| 		outline.addEventListener('keydown',  | ||||
| 			function(evt){ | ||||
| 				var elem = evt.target | ||||
| 				// code editing...
 | ||||
| 				if(elem.nodeName == 'CODE'  | ||||
| 						&& elem.getAttribute('contenteditable') == 'true'){ | ||||
| 					return } | ||||
| 				// update element state...
 | ||||
| 				if(elem.nodeName == 'TEXTAREA'){ | ||||
| 					setTimeout(function(){ | ||||
| @ -795,6 +899,28 @@ var Outline = { | ||||
| 				// handle keyboard...
 | ||||
| 				evt.key in that.keyboard  | ||||
| 					&& that.keyboard[evt.key].call(that, evt) }) | ||||
| 		// update code block...
 | ||||
| 		outline.addEventListener('keyup',  | ||||
| 			function(evt){ | ||||
| 				var elem = evt.target | ||||
| 				// editable code...
 | ||||
| 				if(elem.nodeName == 'CODE'  | ||||
| 						&& elem.getAttribute('contenteditable') == 'true'){ | ||||
| 					// XXX should we clear the syntax???
 | ||||
| 					// XXX do this only if things changed...
 | ||||
| 					delete elem.dataset.highlighted | ||||
| 
 | ||||
| 					var block = that.get(elem) | ||||
| 					var code = block.querySelector('.code') | ||||
| 
 | ||||
| 					var update = elem.innerText | ||||
| 					var i = [...block | ||||
| 							.querySelectorAll('.view code[contenteditable=true]')] | ||||
| 						.indexOf(elem) | ||||
| 					// update element content...
 | ||||
| 					code.value = codeBlock.replace(code.value, i, update) | ||||
| 
 | ||||
| 					return } }) | ||||
| 		// toggle view/code of nodes...
 | ||||
| 		outline.addEventListener('focusin',  | ||||
| 			function(evt){ | ||||
| @ -829,7 +955,8 @@ var Outline = { | ||||
| 				 | ||||
| 				// XXX do a plugin...
 | ||||
| 				window.hljs | ||||
| 					&& hljs.highlightAll() }) | ||||
| 					&& hljs.highlightAll()  | ||||
| 			}) | ||||
| 		// update .code...
 | ||||
| 		var update_code_timeout | ||||
| 		outline.addEventListener('change',  | ||||
| @ -870,6 +997,10 @@ var Outline = { | ||||
| 				.replace(/>/g, '>'))  | ||||
| 			console.log(`Parse: ${Date.now() - t}ms`)} | ||||
| 
 | ||||
| 		// XXX do a plugin...
 | ||||
| 		window.hljs | ||||
| 			&& hljs.highlightAll()  | ||||
| 		 | ||||
| 		return this }, | ||||
| } | ||||
| 
 | ||||
|  | ||||
| @ -26,11 +26,7 @@ var setup = function(){ | ||||
| 	window.editor = { | ||||
| 		__proto__: Outline, | ||||
| 	}.setup( | ||||
| 		document.querySelector('.editor'))  | ||||
| 
 | ||||
| 	// XXX make this a plugin... | ||||
| 	window.hljs | ||||
| 		&& hljs.highlightAll() } | ||||
| 		document.querySelector('.editor')) } | ||||
| 
 | ||||
| </script> | ||||
| </head> | ||||
| @ -56,19 +52,41 @@ var setup = function(){ | ||||
|         an we'll not get here... | ||||
|   - | ||||
| - ## ToDo: | ||||
|   - ASAP: editor: bksapce/del at start/end of a block should join it with prev/next | ||||
|   - ASAP: editor: backsapce/del at start/end of a block should join it with prev/next | ||||
|   - ASAP: editor: pressing enter in text edit mode should split text into two blocks | ||||
|   - ASAP: editor: shifting nodes up/down | ||||
|   - ASAP: use \\t for indent... | ||||
|   - ASAP: scroll into view is bad... | ||||
|   - on item click, place the cursor where it was clicked before the code expanded... | ||||
|   - ~editor: semi-live update styles~ | ||||
|   - need to reach checkboxes via keyboard | ||||
|   - persistent empty first/last node (a button to create a new node) | ||||
|   - add completion percentage to blocks with todo's nested | ||||
|     - _...use `[%]`, `%%`, or something similar..._ | ||||
|   - read-only mode | ||||
|   - should bulets be on the same level as nodes or offset?? | ||||
|   - ASAP: need to reach checkboxes via keyboard | ||||
|   - FEATURE: "percentage complete" in parent blocks with todo's nested | ||||
|     - _...use `[%]` (preferred), `%%`, or something similar..._ | ||||
|   - FEATURE: read-only mode | ||||
|   - FEATURE: `collapse-children:: true` block option -- when loading collapse all immediate children | ||||
|   - FF: figure out a way to draw expand/collapse bullets without the use of CSS' `:has(..)` | ||||
|   - Code blocks and bullets: | ||||
|     - ``` | ||||
|       code | ||||
|       ``` | ||||
|     - _bullet should be either in the middle of the block or at the first line of code (preferred)..._ | ||||
|   - custom element... | ||||
|   - Nerd fonts (option???) | ||||
|   - multiple node selection | ||||
|   - copy/paste nodes/trees | ||||
|   - undo  | ||||
|     collapsed:: true | ||||
|     - delete node | ||||
|     - indent/deindent | ||||
|     - edit node | ||||
|   - Q: can we get the caret line in a textarea??? | ||||
|     - _...this will fix a lot of issues with moving between blocks in edit mode..._ | ||||
|   - Q: do we use \\t for indent? (option???) | ||||
|   - Q: can we place the cursor on item click where it was clicked before before the code expanded? | ||||
|     collapsed:: true | ||||
|     - for example | ||||
|       - #### Click in this line and see where the cursor goes | ||||
|     - _not sure how..._ | ||||
|   - Q: persistent empty first/last node (a button to create a new node)? | ||||
|   - Q: should bullets be on the same level as nodes or offset?? | ||||
|     collapsed:: true | ||||
|     - A) justified to bullet: | ||||
|          * list item | ||||
|          * list item | ||||
| @ -78,8 +96,10 @@ var setup = function(){ | ||||
|          * list item | ||||
|            block text | ||||
|     - NOTE: this is only a problem if making list-items manually -- disable??? | ||||
|   - FF: figure out a way to draw expand/collapse bullets without the use of CSS' `:has(..)` | ||||
|   - Nerd fonts (options?) | ||||
|   - ~Q: can we edit code in a code block directly? (a-la Logseq)~ | ||||
|   - empty item height is a bit off... | ||||
|   - ~`.editor .outline:empty` view and behavior...~ | ||||
|   - ~editor: semi-live update styles~ | ||||
|   - ~do a better expand/collapse icons~ | ||||
|   - ~loading from DOM -- fill textarea~ | ||||
|   - ~focus management~ | ||||
| @ -89,17 +109,29 @@ var setup = function(){ | ||||
|   - ~shift subtree up/down~ | ||||
|   - ~create node~ | ||||
|   - ~edit node~ | ||||
|   - multiple node selection | ||||
|   - copy/paste nodes/trees | ||||
|   - undo  | ||||
|     collapsed:: true | ||||
|     - delete node | ||||
|     - indent/deindent | ||||
|     - edit node | ||||
|   - empty item height is a bit off... | ||||
|   - ~serialize/deserialize~ | ||||
|   - ~add optional text styling to nodes~ | ||||
|   -  | ||||
| - ## Refactoring: | ||||
|   - Item parser (`.__code2html__(..)`) | ||||
|     - split out | ||||
|     - define api | ||||
|     - define a way to extend/stack parsers | ||||
|       _...add wikiwords, ..._ | ||||
|   - Format parser/generator | ||||
|     - split out | ||||
|     - define api | ||||
|     - experiment with clean markdown as format | ||||
|   - CSS | ||||
|     - separate out theming | ||||
|     - separate out settings | ||||
|   - Actions -- move user actions (code in `.keyboard`) into methods | ||||
|   - Move to `keyboard.js` | ||||
|   - Plugin architecture | ||||
|     - Q: do we need `features.js` and/or `actions.js` | ||||
|   - Q: do we need a concatenative API?? | ||||
| 	- `<block>.get() -> <block>` | ||||
|   - | ||||
| - ## TEST | ||||
|   - ### Formatting: | ||||
|     - Styles | ||||
|  | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user