mirror of
				https://github.com/flynx/pWiki.git
				synced 2025-10-31 02:50:08 +00:00 
			
		
		
		
	lots of tweaks and fixes...
Signed-off-by: Alex A. Naanou <alex.nanou@gmail.com>
This commit is contained in:
		
							parent
							
								
									a8797669fe
								
							
						
					
					
						commit
						1934eaf747
					
				| @ -1,9 +1,24 @@ | |||||||
| 
 | 
 | ||||||
|  | /*********************************************************************/ | ||||||
|  | 
 | ||||||
| :root { | :root { | ||||||
| 	--font-size: 5mm; | 	--font-size: 5mm; | ||||||
|  | 
 | ||||||
|  | 	--outline-padding: 5rem; | ||||||
|  | 
 | ||||||
|  | 	--item-indent: 2rem; | ||||||
| 	--item-padding: 0.2em; | 	--item-padding: 0.2em; | ||||||
|  | 
 | ||||||
|  | 	--checkbox-size: 1.5rem; | ||||||
|  | 
 | ||||||
| 	--button-size: 2em; | 	--button-size: 2em; | ||||||
| 
 | 
 | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | /*********************************************************************/ | ||||||
|  | 
 | ||||||
|  | :root { | ||||||
| 	font-family: sans-serif; | 	font-family: sans-serif; | ||||||
| 	font-size: var(--font-size); | 	font-size: var(--font-size); | ||||||
| 
 | 
 | ||||||
| @ -25,22 +40,26 @@ | |||||||
| .editor .outline { | .editor .outline { | ||||||
| 	display: block; | 	display: block; | ||||||
| 	position: relative; | 	position: relative; | ||||||
|  | 
 | ||||||
| 	/* XXX do a better calculation... */ | 	/* XXX do a better calculation... */ | ||||||
| 	width: calc(100% - (var(--button-size) + 4em)); | 	width: calc(100% - var(--button-size) - var(--outline-padding) * 2); | ||||||
|  | 
 | ||||||
|  | 	padding-left: var(--outline-padding); | ||||||
|  | 	padding-right: var(--outline-padding); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| .editor .outline [tabindex] { | .editor .outline [tabindex] { | ||||||
| 	position: relative; | 	position: relative; | ||||||
| } | } | ||||||
| .editor .outline div [tabindex] { | .editor .outline [tabindex] [tabindex] { | ||||||
| 	margin-left: 2em; | 	margin-left: var(--item-indent); | ||||||
| } | } | ||||||
| .editor .outline [tabindex]>span, | .editor .outline [tabindex]>span, | ||||||
| .editor .outline [tabindex]>textarea { | .editor .outline [tabindex]>textarea { | ||||||
| 	display: block; | 	display: block; | ||||||
| 	width: 100%; | 	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 textarea's height here is off too... */ | ||||||
| 	min-height: 1em; | 	min-height: calc(1em + var(--item-padding) * 2); | ||||||
| 	padding-top: var(--item-padding); | 	padding-top: var(--item-padding); | ||||||
| 	padding-bottom: var(--item-padding); | 	padding-bottom: var(--item-padding); | ||||||
| 	padding-left: 0; | 	padding-left: 0; | ||||||
| @ -55,6 +74,9 @@ | |||||||
| 	outline: none; | 	outline: none; | ||||||
| 	border: none; | 	border: none; | ||||||
| } | } | ||||||
|  | .editor .outline [tabindex]>span:blank { | ||||||
|  | 	content: " "; | ||||||
|  | } | ||||||
| .editor .outline [tabindex]>textarea { | .editor .outline [tabindex]>textarea { | ||||||
| 	height: calc(2 * var(--item-padding) + 1em); | 	height: calc(2 * var(--item-padding) + 1em); | ||||||
| 	overflow: hidden; | 	overflow: hidden; | ||||||
| @ -87,7 +109,66 @@ | |||||||
| .editor .outline div[collapsed] { | .editor .outline div[collapsed] { | ||||||
| 	border-bottom: solid 1px silver; | 	border-bottom: solid 1px silver; | ||||||
| } | } | ||||||
| .editor .outline div[collapsed] div { | /* expand/collapse button... */ | ||||||
|  | .editor .outline [tabindex]:after { | ||||||
|  | 	--size: 0.5rem; | ||||||
|  | 
 | ||||||
|  | 	content: ""; | ||||||
|  | 	position: absolute; | ||||||
|  | 	display: inline-block; | ||||||
|  | 	top: calc(1em / 2); | ||||||
|  | 	right: calc(-1rem + -1 * var(--size) - var(--item-padding)); | ||||||
|  | 	width: 0; | ||||||
|  | 	height: 0; | ||||||
|  | 	border: solid calc(var(--size) / 1.2) transparent; | ||||||
|  | 	border-top: solid var(--size) black; | ||||||
|  | 	opacity: 0; | ||||||
|  | } | ||||||
|  | .editor .outline [tabindex][collapsed]:after { | ||||||
|  | 	border: solid calc(var(--size) / 1.2) transparent; | ||||||
|  | 	border-left: solid var(--size) black; | ||||||
|  | 	margin-right: -0.25rem; | ||||||
|  | 	opacity: 0.1; | ||||||
|  | } | ||||||
|  | .editor .outline [tabindex]:hover:after { | ||||||
|  | 	opacity: 0.1; | ||||||
|  | } | ||||||
|  | /* click/tap zone for expand button... */ | ||||||
|  | .editor .outline [tabindex]>span:before { | ||||||
|  | 	content: ""; | ||||||
|  | 	position: absolute; | ||||||
|  | 	display: inline-block; | ||||||
|  | 	right: -2rem; | ||||||
|  | 	width: 2rem; | ||||||
|  | 	height: calc(1em + var(--item-padding) * 2); | ||||||
|  | } | ||||||
|  | /* | ||||||
|  | .editor .outline div[collapsed]:before, | ||||||
|  | .editor .outline div[collapsed]:after { | ||||||
|  | 	--size: 0.3em; | ||||||
|  | 
 | ||||||
|  | 	content: ""; | ||||||
|  | 	display: inline-block; | ||||||
|  | 	position: absolute; | ||||||
|  | 	width: var(--size); | ||||||
|  | 	height: var(--size); | ||||||
|  | 	bottom: 0; | ||||||
|  | 	right: calc(-1 * var(--size)); | ||||||
|  | 	margin-bottom: calc(var(--size) / -2 - 0.5px); | ||||||
|  | 	rotate: -45deg; | ||||||
|  | 	box-sizing: border-box; | ||||||
|  | 
 | ||||||
|  | 	color: silver; | ||||||
|  | 	border-top: solid 1px silver; | ||||||
|  | 	border-left: solid 1px silver; | ||||||
|  | } | ||||||
|  | .editor .outline div[collapsed]:before { | ||||||
|  | 	right: auto; | ||||||
|  | 	left: calc(-1 * var(--size)); | ||||||
|  | 	rotate: 135deg; | ||||||
|  | } | ||||||
|  | */ | ||||||
|  | .editor .outline div[collapsed] [tabindex] { | ||||||
| 	display: none; | 	display: none; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| @ -119,6 +200,7 @@ | |||||||
| /*-------------------------------------------------------------------*/ | /*-------------------------------------------------------------------*/ | ||||||
| /* Styles */ | /* Styles */ | ||||||
| 
 | 
 | ||||||
|  | /* Headings... */ | ||||||
| .editor .outline .heading-1>span, | .editor .outline .heading-1>span, | ||||||
| .editor .outline .heading-1>textarea, | .editor .outline .heading-1>textarea, | ||||||
| .editor .outline .heading-2>span, | .editor .outline .heading-2>span, | ||||||
| @ -139,7 +221,7 @@ | |||||||
| .editor .outline .heading-2>textarea, | .editor .outline .heading-2>textarea, | ||||||
| .editor .outline .heading-3>span, | .editor .outline .heading-3>span, | ||||||
| .editor .outline .heading-3>textarea { | .editor .outline .heading-3>textarea { | ||||||
| 	border-bottom: solid 1px rgba(0,0,0,0.05); | 	border-bottom: solid 1px rgba(0,0,0,0.1); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| .editor .outline .heading-1>span, | .editor .outline .heading-1>span, | ||||||
| @ -195,24 +277,48 @@ | |||||||
| 	color: silver; | 	color: silver; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| .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)); |  | ||||||
| 
 | 
 | ||||||
| 	top: calc(0.6em + var(--item-padding)); | /* checkboxes... */ | ||||||
| 	height: var(--size); | :root { | ||||||
| 	width: var(--size); | 	/* NOTE: this must have a unit... */ | ||||||
| 	margin-top: calc(var(--size) / -2); | 	/* XXX move this to the config when fixed... */ | ||||||
|  | 	/* XXX setting this to >0em will add margins to both sides of  | ||||||
|  | 	* 	the inline checkbox even if it is the first thing in the  | ||||||
|  | 	* 	element -- can's seem to figure out a way to avoid this */ | ||||||
|  | 	--checkbox-margin: 0em; | ||||||
|  | } | ||||||
|  | /* align todo checkboxes to indnt (otherwise they are on the indent) */ | ||||||
|  | .editor .outline [tabindex].todo>span { | ||||||
|  | 	margin-left: var(--checkbox-size); | ||||||
|  | 	padding-left: calc( | ||||||
|  | 		var(--item-padding) | ||||||
|  | 		+ var(--checkbox-margin) * 2); | ||||||
|  | } | ||||||
|  | .editor .outline [tabindex].check>span>input[type=checkbox], | ||||||
|  | .editor .outline [tabindex].todo>span>input[type=checkbox] { | ||||||
|  | 	height: var(--checkbox-size); | ||||||
|  | 	width: var(--checkbox-size); | ||||||
|  | 
 | ||||||
|  | 	margin-top: calc(var(--checkbox-size) / -2); | ||||||
|  | 	margin-left: var(--checkbox-margin); | ||||||
|  | 	margin-right: var(--checkbox-margin); | ||||||
|  | 
 | ||||||
|  | 	transform: translateY(calc(2 * var(--item-padding))); | ||||||
| 
 | 
 | ||||||
| 	/* NOTE: this appears to be needed for the em sizes above to work correctly */ | 	/* NOTE: this appears to be needed for the em sizes above to work correctly */ | ||||||
| 	font-size: 1em; | 	font-size: 1em; | ||||||
| } | } | ||||||
| .editor .outline [tabindex]>span>input[type=checkbox].todo { | .editor .outline [tabindex].todo>span>input[type=checkbox]:first-child { | ||||||
| 	position: absolute; | 	margin-left: calc( | ||||||
| 	margin-left: calc(-1 * var(--size) - var(--item-padding) * 2); | 		var(--checkbox-size) * -1 | ||||||
|  | 		- var(--item-padding) | ||||||
|  | 		- var(--checkbox-margin) * 2); | ||||||
|  | 	margin-right: calc( | ||||||
|  | 		var(--item-padding) | ||||||
|  | 		+ var(--checkbox-margin)); | ||||||
| } | } | ||||||
| .editor .outline [tabindex]>span>input[type=checkbox].check { | /* XXX need to remove left margin from strictly the first itme in block... */ | ||||||
| 	transform: translateY(calc(2 * var(--item-padding))); | .editor .outline [tabindex].check>span>input[type=checkbox] { | ||||||
|  | 	/*margin-left: 0;*/ | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -195,7 +195,7 @@ var Outline = { | |||||||
| 				// heading...
 | 				// heading...
 | ||||||
| 				parsed.style ? | 				parsed.style ? | ||||||
| 					node.classList.add(...parsed.style) | 					node.classList.add(...parsed.style) | ||||||
| 					: node.classList.remove(...this.__styles__) | 					: node.classList.remove(...this.__styles) | ||||||
| 			} else { | 			} else { | ||||||
| 				html.innerHTML = data.text } | 				html.innerHTML = data.text } | ||||||
| 			text.value = data.text | 			text.value = data.text | ||||||
| @ -259,7 +259,9 @@ var Outline = { | |||||||
| 		if(elem.classList.contains('focused')){ | 		if(elem.classList.contains('focused')){ | ||||||
| 			// XXX need to be able to get the next elem on same level...
 | 			// XXX need to be able to get the next elem on same level...
 | ||||||
| 			this.toggleCollapse(elem, true) | 			this.toggleCollapse(elem, true) | ||||||
| 			next = this.get(elem, 'next') } | 			next = elem === this.get(-1) ? | ||||||
|  | 				this.get(elem, 'prev')  | ||||||
|  | 				: this.get(elem, 'next') } | ||||||
| 		elem?.remove() | 		elem?.remove() | ||||||
| 		next?.focus() | 		next?.focus() | ||||||
| 		return this }, | 		return this }, | ||||||
| @ -269,33 +271,27 @@ var Outline = { | |||||||
| 		return this }, | 		return this }, | ||||||
| 
 | 
 | ||||||
| 	// block serialization...
 | 	// block serialization...
 | ||||||
| 	// XXX shouild we support headings + other formatting per block???
 |  | ||||||
| 	// XXX split this up into a generic handler + plugins...
 | 	// XXX split this up into a generic handler + plugins...
 | ||||||
| 	// XXX need a way to filter input text...
 | 	// XXX need a way to filter input text...
 | ||||||
| 	// 		use-case: hidden attributes...
 | 	// 		use-case: hidden attributes...
 | ||||||
| 	__styles__: [ | 	// NOTE: this is auto-populated by .__code2html__(..)
 | ||||||
| 		'heading-1', | 	__styles: undefined, | ||||||
| 		'heading-2', |  | ||||||
| 		'heading-3', |  | ||||||
| 		'heading-4', |  | ||||||
| 		'heading-5', |  | ||||||
| 		'heading-6', |  | ||||||
| 		'list', |  | ||||||
| 	], |  | ||||||
| 	__code2html__: function(code){ | 	__code2html__: function(code){ | ||||||
|  | 		var that = this | ||||||
| 		var elem = { | 		var elem = { | ||||||
| 			collapsed: false, | 			collapsed: false, | ||||||
| 		} | 		} | ||||||
| 		var heading = function(level){ | 		var style = function(style, code=undefined){ | ||||||
|  | 			style = [style].flat() | ||||||
|  | 			that.__styles = [...new Set([ | ||||||
|  | 				...(that.__styles ?? []), | ||||||
|  | 				...style, | ||||||
|  | 			])] | ||||||
| 			return function(_, text){ | 			return function(_, text){ | ||||||
| 				elem.style ??= [] | 				elem.style ??= [] | ||||||
| 				elem.style.push('heading-'+level) | 				elem.style.push(...style) | ||||||
| 				return text } } | 				return code  | ||||||
| 		var style = function(style){ | 					?? text } } | ||||||
| 			return function(_, text){ |  | ||||||
| 				elem.style ??= [] |  | ||||||
| 				elem.style.push(style) |  | ||||||
| 				return text } } |  | ||||||
| 		elem.text = code  | 		elem.text = code  | ||||||
| 			// hidden attributes...
 | 			// hidden attributes...
 | ||||||
| 			// XXX make this generic...
 | 			// XXX make this generic...
 | ||||||
| @ -328,12 +324,12 @@ var Outline = { | |||||||
| 			// elements...
 | 			// elements...
 | ||||||
| 			.replace(/(\n|^)---*\h*(\n|$)/m, '$1<hr>') | 			.replace(/(\n|^)---*\h*(\n|$)/m, '$1<hr>') | ||||||
| 			// ToDo...
 | 			// ToDo...
 | ||||||
| 			.replace(/^TODO\s*(.*)$/m, '<input class="todo" type="checkbox">$1') | 			.replace(/^TODO\s*/m, style('todo', '<input type="checkbox">')) | ||||||
| 			.replace(/^DONE\s*(.*)$/m, '<input class="todo" type="checkbox" checked>$1') | 			.replace(/^DONE\s*/m, style('todo', '<input type="checkbox" checked>')) | ||||||
| 			// checkboxes...
 | 			// checkboxes...
 | ||||||
| 			// XXX these can not be clicked (yet)...
 | 			// XXX these can not be clicked (yet)...
 | ||||||
| 			.replace(/\[_\]/gm, '<input class="check" type="checkbox">') | 			.replace(/\[_\]/gm, style('check', '<input class="check" type="checkbox">')) | ||||||
| 			.replace(/\[[X]\]/gm, '<input class="check" type="checkbox" checked>') | 			.replace(/\[[X]\]/gm, style('check', '<input class="check" type="checkbox" checked>')) | ||||||
| 			// basic styling...
 | 			// basic styling...
 | ||||||
| 			// XXX these are quite naive...
 | 			// XXX these are quite naive...
 | ||||||
| 			.replace(/\*(.*)\*/gm, '<b>$1</b>') | 			.replace(/\*(.*)\*/gm, '<b>$1</b>') | ||||||
| @ -427,6 +423,7 @@ var Outline = { | |||||||
| 		var block = document.createElement('div') | 		var block = document.createElement('div') | ||||||
| 		block.setAttribute('tabindex', '0') | 		block.setAttribute('tabindex', '0') | ||||||
| 		var text = document.createElement('textarea') | 		var text = document.createElement('textarea') | ||||||
|  | 			.autoUpdateSize() | ||||||
| 		var html = document.createElement('span') | 		var html = document.createElement('span') | ||||||
| 		block.append(text, html) | 		block.append(text, html) | ||||||
| 		this.update(block, data) | 		this.update(block, data) | ||||||
| @ -440,6 +437,9 @@ var Outline = { | |||||||
| 					&& (cur.querySelector('[tabindex]') | 					&& (cur.querySelector('[tabindex]') | ||||||
| 						|| cur.nextElementSibling)) ? | 						|| cur.nextElementSibling)) ? | ||||||
| 				this.get(place).before(block) | 				this.get(place).before(block) | ||||||
|  | 			: (place == 'next'  | ||||||
|  | 					&& !cur.nextElementSibling) ? | ||||||
|  | 				cur.after(block) | ||||||
| 			: (place == 'before' || place == 'after') ? | 			: (place == 'before' || place == 'after') ? | ||||||
| 				cur[place](block) | 				cur[place](block) | ||||||
| 			: undefined } | 			: undefined } | ||||||
| @ -609,6 +609,10 @@ var Outline = { | |||||||
| 		outline.addEventListener('click',  | 		outline.addEventListener('click',  | ||||||
| 			function(evt){ | 			function(evt){ | ||||||
| 				var elem = evt.target | 				var elem = evt.target | ||||||
|  | 				// expand/collapse...
 | ||||||
|  | 				// XXX
 | ||||||
|  | 				if(elem.getAttribute('collapsed')){ | ||||||
|  | 				} | ||||||
| 				// todo: toggle checkbox...
 | 				// todo: toggle checkbox...
 | ||||||
| 				if(elem.classList.contains('todo')){ | 				if(elem.classList.contains('todo')){ | ||||||
| 					var node = elem.parentElement.parentElement | 					var node = elem.parentElement.parentElement | ||||||
|  | |||||||
| @ -28,7 +28,14 @@ var setup = function(){ | |||||||
| 	<!-- code --> | 	<!-- code --> | ||||||
| 	<div class="code"> | 	<div class="code"> | ||||||
| - # Outline editor prototype | - # Outline editor prototype | ||||||
|  |   - An outline-based markdown editor experiment | ||||||
|  |   - ### Infuences:: | ||||||
|  |     - Logseq | ||||||
|  | 	- Tomboy | ||||||
|  | 	- Bonsai | ||||||
|  |   -  | ||||||
| - ## ToDo | - ## ToDo | ||||||
|  |   - read-only mode | ||||||
|   - 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 | ||||||
| @ -51,7 +58,8 @@ var setup = function(){ | |||||||
|     - indent/deindent |     - indent/deindent | ||||||
|     - edit node |     - edit node | ||||||
|   - copy/paste nodes/trees |   - copy/paste nodes/trees | ||||||
|   - markdown tables |   - markdown: tables | ||||||
|  |   - empty item height is a bit off... | ||||||
|   - ~serialize~/deserialize |   - ~serialize~/deserialize | ||||||
|   - ~add optional text styling to nodes~ |   - ~add optional text styling to nodes~ | ||||||
|   -  |   -  | ||||||
| @ -77,8 +85,9 @@ var setup = function(){ | |||||||
|     - Basic inline *bold*, _italic_ and ~striked~ |     - Basic inline *bold*, _italic_ and ~striked~ | ||||||
| 	- To do items | 	- To do items | ||||||
| 	  - TODO undone item | 	  - TODO undone item | ||||||
| 	  - DONE done item |  | ||||||
|         _(clicking the checkbox updates the item)_ |         _(clicking the checkbox updates the item)_ | ||||||
|  | 	  - DONE done item | ||||||
|  | 	  - [_] a different way to draw a checkbox | ||||||
|     - Inline [X] checkboxes [_] |     - Inline [X] checkboxes [_] | ||||||
|   - A |   - A | ||||||
|     collapsed:: true |     collapsed:: true | ||||||
|  | |||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user