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 { | ||||
| 	--font-size: 5mm; | ||||
| 
 | ||||
| 	--outline-padding: 5rem; | ||||
| 
 | ||||
| 	--item-indent: 2rem; | ||||
| 	--item-padding: 0.2em; | ||||
| 
 | ||||
| 	--checkbox-size: 1.5rem; | ||||
| 
 | ||||
| 	--button-size: 2em; | ||||
| 
 | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| /*********************************************************************/ | ||||
| 
 | ||||
| :root { | ||||
| 	font-family: sans-serif; | ||||
| 	font-size: var(--font-size); | ||||
| 
 | ||||
| @ -25,22 +40,26 @@ | ||||
| .editor .outline { | ||||
| 	display: block; | ||||
| 	position: relative; | ||||
| 
 | ||||
| 	/* 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] { | ||||
| 	position: relative; | ||||
| } | ||||
| .editor .outline div [tabindex] { | ||||
| 	margin-left: 2em; | ||||
| .editor .outline [tabindex] [tabindex] { | ||||
| 	margin-left: var(--item-indent); | ||||
| } | ||||
| .editor .outline [tabindex]>span, | ||||
| .editor .outline [tabindex]>textarea { | ||||
| 	display: block; | ||||
| 	width: 100%; | ||||
| 	/* 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-bottom: var(--item-padding); | ||||
| 	padding-left: 0; | ||||
| @ -55,6 +74,9 @@ | ||||
| 	outline: none; | ||||
| 	border: none; | ||||
| } | ||||
| .editor .outline [tabindex]>span:blank { | ||||
| 	content: " "; | ||||
| } | ||||
| .editor .outline [tabindex]>textarea { | ||||
| 	height: calc(2 * var(--item-padding) + 1em); | ||||
| 	overflow: hidden; | ||||
| @ -87,7 +109,66 @@ | ||||
| .editor .outline div[collapsed] { | ||||
| 	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; | ||||
| } | ||||
| 
 | ||||
| @ -119,6 +200,7 @@ | ||||
| /*-------------------------------------------------------------------*/ | ||||
| /* Styles */ | ||||
| 
 | ||||
| /* Headings... */ | ||||
| .editor .outline .heading-1>span, | ||||
| .editor .outline .heading-1>textarea, | ||||
| .editor .outline .heading-2>span, | ||||
| @ -139,7 +221,7 @@ | ||||
| .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); | ||||
| 	border-bottom: solid 1px rgba(0,0,0,0.1); | ||||
| } | ||||
| 
 | ||||
| .editor .outline .heading-1>span, | ||||
| @ -195,24 +277,48 @@ | ||||
| 	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)); | ||||
| 	height: var(--size); | ||||
| 	width: var(--size); | ||||
| 	margin-top: calc(var(--size) / -2); | ||||
| /* checkboxes... */ | ||||
| :root { | ||||
| 	/* NOTE: this must have a unit... */ | ||||
| 	/* 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 */ | ||||
| 	font-size: 1em; | ||||
| } | ||||
| .editor .outline [tabindex]>span>input[type=checkbox].todo { | ||||
| 	position: absolute; | ||||
| 	margin-left: calc(-1 * var(--size) - var(--item-padding) * 2); | ||||
| .editor .outline [tabindex].todo>span>input[type=checkbox]:first-child { | ||||
| 	margin-left: calc( | ||||
| 		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 { | ||||
| 	transform: translateY(calc(2 * var(--item-padding))); | ||||
| /* XXX need to remove left margin from strictly the first itme in block... */ | ||||
| .editor .outline [tabindex].check>span>input[type=checkbox] { | ||||
| 	/*margin-left: 0;*/ | ||||
| } | ||||
| 
 | ||||
|  | ||||
| @ -195,7 +195,7 @@ var Outline = { | ||||
| 				// heading...
 | ||||
| 				parsed.style ? | ||||
| 					node.classList.add(...parsed.style) | ||||
| 					: node.classList.remove(...this.__styles__) | ||||
| 					: node.classList.remove(...this.__styles) | ||||
| 			} else { | ||||
| 				html.innerHTML = data.text } | ||||
| 			text.value = data.text | ||||
| @ -259,7 +259,9 @@ var Outline = { | ||||
| 		if(elem.classList.contains('focused')){ | ||||
| 			// XXX need to be able to get the next elem on same level...
 | ||||
| 			this.toggleCollapse(elem, true) | ||||
| 			next = this.get(elem, 'next') } | ||||
| 			next = elem === this.get(-1) ? | ||||
| 				this.get(elem, 'prev')  | ||||
| 				: this.get(elem, 'next') } | ||||
| 		elem?.remove() | ||||
| 		next?.focus() | ||||
| 		return this }, | ||||
| @ -269,33 +271,27 @@ var Outline = { | ||||
| 		return this }, | ||||
| 
 | ||||
| 	// block serialization...
 | ||||
| 	// XXX shouild we support headings + other formatting per block???
 | ||||
| 	// 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', | ||||
| 		'heading-3', | ||||
| 		'heading-4', | ||||
| 		'heading-5', | ||||
| 		'heading-6', | ||||
| 		'list', | ||||
| 	], | ||||
| 	// NOTE: this is auto-populated by .__code2html__(..)
 | ||||
| 	__styles: undefined, | ||||
| 	__code2html__: function(code){ | ||||
| 		var that = this | ||||
| 		var elem = { | ||||
| 			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){ | ||||
| 				elem.style ??= [] | ||||
| 				elem.style.push('heading-'+level) | ||||
| 				return text } } | ||||
| 		var style = function(style){ | ||||
| 			return function(_, text){ | ||||
| 				elem.style ??= [] | ||||
| 				elem.style.push(style) | ||||
| 				return text } } | ||||
| 				elem.style.push(...style) | ||||
| 				return code  | ||||
| 					?? text } } | ||||
| 		elem.text = code  | ||||
| 			// hidden attributes...
 | ||||
| 			// XXX make this generic...
 | ||||
| @ -328,12 +324,12 @@ var Outline = { | ||||
| 			// elements...
 | ||||
| 			.replace(/(\n|^)---*\h*(\n|$)/m, '$1<hr>') | ||||
| 			// ToDo...
 | ||||
| 			.replace(/^TODO\s*(.*)$/m, '<input class="todo" type="checkbox">$1') | ||||
| 			.replace(/^DONE\s*(.*)$/m, '<input class="todo" type="checkbox" checked>$1') | ||||
| 			.replace(/^TODO\s*/m, style('todo', '<input type="checkbox">')) | ||||
| 			.replace(/^DONE\s*/m, style('todo', '<input type="checkbox" checked>')) | ||||
| 			// checkboxes...
 | ||||
| 			// XXX these can not be clicked (yet)...
 | ||||
| 			.replace(/\[_\]/gm, '<input class="check" type="checkbox">') | ||||
| 			.replace(/\[[X]\]/gm, '<input class="check" type="checkbox" checked>') | ||||
| 			.replace(/\[_\]/gm, style('check', '<input class="check" type="checkbox">')) | ||||
| 			.replace(/\[[X]\]/gm, style('check', '<input class="check" type="checkbox" checked>')) | ||||
| 			// basic styling...
 | ||||
| 			// XXX these are quite naive...
 | ||||
| 			.replace(/\*(.*)\*/gm, '<b>$1</b>') | ||||
| @ -427,6 +423,7 @@ var Outline = { | ||||
| 		var block = document.createElement('div') | ||||
| 		block.setAttribute('tabindex', '0') | ||||
| 		var text = document.createElement('textarea') | ||||
| 			.autoUpdateSize() | ||||
| 		var html = document.createElement('span') | ||||
| 		block.append(text, html) | ||||
| 		this.update(block, data) | ||||
| @ -440,6 +437,9 @@ var Outline = { | ||||
| 					&& (cur.querySelector('[tabindex]') | ||||
| 						|| cur.nextElementSibling)) ? | ||||
| 				this.get(place).before(block) | ||||
| 			: (place == 'next'  | ||||
| 					&& !cur.nextElementSibling) ? | ||||
| 				cur.after(block) | ||||
| 			: (place == 'before' || place == 'after') ? | ||||
| 				cur[place](block) | ||||
| 			: undefined } | ||||
| @ -609,6 +609,10 @@ var Outline = { | ||||
| 		outline.addEventListener('click',  | ||||
| 			function(evt){ | ||||
| 				var elem = evt.target | ||||
| 				// expand/collapse...
 | ||||
| 				// XXX
 | ||||
| 				if(elem.getAttribute('collapsed')){ | ||||
| 				} | ||||
| 				// todo: toggle checkbox...
 | ||||
| 				if(elem.classList.contains('todo')){ | ||||
| 					var node = elem.parentElement.parentElement | ||||
|  | ||||
| @ -28,7 +28,14 @@ var setup = function(){ | ||||
| 	<!-- code --> | ||||
| 	<div class="code"> | ||||
| - # Outline editor prototype | ||||
|   - An outline-based markdown editor experiment | ||||
|   - ### Infuences:: | ||||
|     - Logseq | ||||
| 	- Tomboy | ||||
| 	- Bonsai | ||||
|   -  | ||||
| - ## ToDo | ||||
|   - read-only mode | ||||
|   - 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 | ||||
| @ -51,7 +58,8 @@ var setup = function(){ | ||||
|     - indent/deindent | ||||
|     - edit node | ||||
|   - copy/paste nodes/trees | ||||
|   - markdown tables | ||||
|   - markdown: tables | ||||
|   - empty item height is a bit off... | ||||
|   - ~serialize~/deserialize | ||||
|   - ~add optional text styling to nodes~ | ||||
|   -  | ||||
| @ -77,8 +85,9 @@ var setup = function(){ | ||||
|     - Basic inline *bold*, _italic_ and ~striked~ | ||||
| 	- To do items | ||||
| 	  - TODO undone item | ||||
| 	  - DONE done item | ||||
|         _(clicking the checkbox updates the item)_ | ||||
| 	  - DONE done item | ||||
| 	  - [_] a different way to draw a checkbox | ||||
|     - Inline [X] checkboxes [_] | ||||
|   - A | ||||
|     collapsed:: true | ||||
|  | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user