From b301fcfa38d3d152c0516b1f797bde3d616d8bb5 Mon Sep 17 00:00:00 2001 From: Nicolas Sanchez Date: Wed, 1 Mar 2023 15:09:22 +0100 Subject: [PATCH] manage selection --- pages/accueil.md | 1 + pages/index.md | 4 +- pages/test.md | 3 + static/modules/caret.js | 121 +++++++++++++++++++++++++++++++++- static/modules/cheezenotes.js | 52 +++++++++++---- static/modules/md.js | 44 ++++++++++--- templates/page.html | 2 +- 7 files changed, 203 insertions(+), 24 deletions(-) create mode 100644 pages/test.md diff --git a/pages/accueil.md b/pages/accueil.md index 15c0c60..b27ea3e 100644 --- a/pages/accueil.md +++ b/pages/accueil.md @@ -2,3 +2,4 @@ # Accueil ## [Notes](notes) ## [Cuisine](cuisine) +[Page de tests pour le développement de CheezeNotes](test) \ No newline at end of file diff --git a/pages/index.md b/pages/index.md index 0ed2a37..2bb31ff 100644 --- a/pages/index.md +++ b/pages/index.md @@ -1,6 +1,7 @@ +[Accueil](accueil) # CheezeNotes L'objectif de CheezeNotes est de pouvoir saisir des notes avec un minimum de formatage le plus rapidement possible. -> Cette page est un bac à sable. Les modifications ne seront jamais enregistrées. +> Cette page est un bac à sable. Les modifications ne seront jamais enregistrées. > Pour réinitialiser la page, il suffit de la recharger. ## Utilisation Pour passer en mode édition, il suffit de cliquer sur le texte à modifier. @@ -21,6 +22,7 @@ Il y a 4 niveaux de titres : |`*italic*`|*italic*|| |`__gras__`|__gras__|| |`_italic_`|_italic_|| +|`~~barré~~`|~~barré~~|| |`***gras_italic***`|***gras_italic***|| |`___gras_italic___`|___gras_italic___|Non| |`__*gras_italic*__`|__*gras_italic*__|| diff --git a/pages/test.md b/pages/test.md new file mode 100644 index 0000000..4d17437 --- /dev/null +++ b/pages/test.md @@ -0,0 +1,3 @@ +[Accueil](accueil) +# Test pour développement CheezeNotes +test de gras au milieu d'un texte \ No newline at end of file diff --git a/static/modules/caret.js b/static/modules/caret.js index 686d1f0..6bab702 100644 --- a/static/modules/caret.js +++ b/static/modules/caret.js @@ -1,3 +1,47 @@ +function insertTextAtCaret(txtBefore, txtAfter = '') { + let ret = saveSelection(); + let line = ret[0]; + let start = ret[1]; + let end = ret[3]; + let txt = line.innerText; + let before = '' + if (start == 0) { + } else { + before = txt.substring(0, start); + } + let after = txt.substring(end, txt.length); + let selection = ''; + if (end > start) { + selection = txt.substring(start, end); + } + line.innerHTML = before + txtBefore + selection + txtAfter + after; + let span = document.createElement('span'); + if (start == end && ret[0] == ret[2]) { + span.innerHTML = txtBefore; + ret[1] = start + span.innerText.length; + ret[3] = ret[1]; + } else { + span.innerHTML = txtBefore + txtAfter; + ret[3] = end + span.innerText.length; + } + loadSelection(ret); +} + +function saveSelection() { + let ret = getStartPositionInLine(); + let startLine = ret[0]; + let startPosition = ret[1]; + ret = getEndPositionInLine(); + let endLine = ret[0]; + let endPosition = ret[1]; + return [startLine, startPosition, endLine, endPosition]; +} + +function loadSelection(sel) { + setStartPositionInLine(sel[0], sel[1]); + setEndPositionInLine(sel[2], sel[3]); +} + function getStartPositionInLine() { let selection = window.getSelection(); if (selection.rangeCount == 0) { @@ -71,4 +115,79 @@ function setStartPositionInText(obj, position) { return 0; } -export { getStartPositionInLine, setStartPositionInLine }; \ No newline at end of file +function getEndPositionInLine() { + let selection = window.getSelection(); + if (selection.rangeCount == 0) { + return [null, 0]; + } + let range = selection.getRangeAt(0).cloneRange(); + let obj = range.endContainer; + + let position = range.endOffset; + + if (obj.nodeName == 'DIV' && obj.classList.contains('cheezenotes_line')) { + return [obj, position]; + } + + let line = null; + + while (obj != null) { + if (obj.previousSibling != null) { + obj = obj.previousSibling; + if (obj.innerText != null) { + position += obj.innerText.length; + } else if (obj.length != null) { + position += obj.length; + } + } else if (obj.parentNode != null && obj.parentNode.classList != null && !obj.parentNode.classList.contains('cheezenotes_line')) { + obj = obj.parentNode; + } else if (obj.parentNode != null && obj.parentNode.classList != null && obj.parentNode.classList.contains('cheezenotes_line')) { + line = obj.parentNode; + obj = null; + } else { + obj = null; + } + } + return [line, position]; +} + +function setEndPositionInLine(line, position) { + setEndPositionInDiv(line, position) +} + +function setEndPositionInDiv(obj, position) { + let temppos = position; + if (temppos > obj.innerText.length) { + return temppos - obj.innerText.length; + } + let children = obj.childNodes; + for (let i = 0; i < children.length; i++) { + let child = children[i]; + if (child.nodeType == 3) { + temppos = setEndPositionInText(child, temppos); + } else { + temppos = setEndPositionInDiv(child, temppos); + } + if (temppos == 0) { + return temppos; + } + } + return temppos; +} + +function setEndPositionInText(obj, position) { + if (position > obj.length) { + return position - obj.length; + } + + let selection = window.getSelection(); + let oldRange = selection.getRangeAt(0); + let range = document.createRange(); + range.setStart(oldRange.startContainer, oldRange.startOffset); + range.setEnd(obj, position); + selection.removeAllRanges(); + selection.addRange(range); + return 0; +} + +export { saveSelection, loadSelection, insertTextAtCaret }; \ No newline at end of file diff --git a/static/modules/cheezenotes.js b/static/modules/cheezenotes.js index 4259280..4ae21dc 100644 --- a/static/modules/cheezenotes.js +++ b/static/modules/cheezenotes.js @@ -1,4 +1,4 @@ -import { getStartPositionInLine, setStartPositionInLine } from './caret.js'; +import { saveSelection, loadSelection, insertTextAtCaret } from './caret.js'; import { formatLine, load, save, formatTable, redrawTables, appendData, dpwidth } from './md.js'; function timeoutSave() { @@ -17,6 +17,33 @@ function ontextarea(e) { } } +function onboldbutton(e) { + e.preventDefault(); + let cheezenotes = document.getElementById('cheezenotes'); + cheezenotes.focus(); + insertTextAtCaret('**', '**'); + onedit(e); + return false; +} + +function onitalicbutton(e) { + e.preventDefault(); + let cheezenotes = document.getElementById('cheezenotes'); + cheezenotes.focus(); + insertTextAtCaret('_', '_'); + onedit(e); + return false; +} + +function onstrikebutton(e) { + e.preventDefault(); + let cheezenotes = document.getElementById('cheezenotes'); + cheezenotes.focus(); + insertTextAtCaret('~~', '~~'); + onedit(e); + return false; +} + function onsave(e) { let saveButton = document.getElementById('saveButton'); saveButton.disabled = true; @@ -45,7 +72,7 @@ function onedit(e) { timeoutSave(); saveButton.disabled = false; - let ret = getStartPositionInLine(); + let ret = saveSelection(); let line = ret[0]; let position = ret[1]; @@ -64,7 +91,9 @@ function onedit(e) { let newline = formatLine(line.innerText); line.parentNode.replaceChild(newline, line); formatTable(newline, dpwidth()); - setStartPositionInLine(newline, position); + ret[0] = newline; + ret[2] = newline; + loadSelection(ret); console.log('onedit fin'); } @@ -75,16 +104,7 @@ function onkeydown(e) { e.preventDefault(); let key = ' '; - let ret = getStartPositionInLine(); - let line = ret[0]; - let position = ret[1]; - let txt = line.innerText; - if (position == 0) { - line.innerHTML = key + txt; // 4 espaces =>   - } else { - line.innerHTML = txt.substring(0, position) + key + txt.substring(position, txt.length); - } - setStartPositionInLine(line, position + 1); + insertTextAtCaret(key); onedit(e); return false; } @@ -175,6 +195,12 @@ function init(pagename = null) { taButton.addEventListener('click', ontextarea); let lockButton = document.getElementById('lockButton'); lockButton.addEventListener('click', onlockbutton); + let boldButton = document.getElementById('boldButton'); + boldButton.addEventListener('mousedown', onboldbutton); + let italicButton = document.getElementById('italicButton'); + italicButton.addEventListener('mousedown', onitalicbutton); + let strikeButton = document.getElementById('strikeButton'); + strikeButton.addEventListener('mousedown', onstrikebutton); onload(); } diff --git a/static/modules/md.js b/static/modules/md.js index 186633e..5887045 100644 --- a/static/modules/md.js +++ b/static/modules/md.js @@ -1,4 +1,4 @@ -import { getStartPositionInLine, setStartPositionInLine } from "./caret.js"; +import { saveSelection, loadSelection } from "./caret.js"; function load(textarea, div) { div.innerHTML = ''; @@ -14,7 +14,7 @@ function load(textarea, div) { function appendData(div, data) { const selection = window.getSelection(); selection.deleteFromDocument(); - let ret = getStartPositionInLine(); + let ret = saveSelection(); let line = ret[0]; let position = ret[1]; if (line == null) { @@ -41,7 +41,7 @@ function appendData(div, data) { prevline.after(newline); position = lines[lines.length - 1].length; } - setStartPositionInLine(newline, position); + loadSelection([newline, position, newline, position]); redrawTables(div, dpwidth(div)); } @@ -125,9 +125,9 @@ function formatLine(line) { line = ret[0]; let listMono = ret[1]; - // test remove link ret = removeLink(line); - console.log('removeLink ' + ret[0]); + line = ret[0]; + let listLink = ret[1]; if (line.match(/^\s*_{3,}\s*$/)) { token = /^(\s*_{3,}\s*)$/ @@ -195,10 +195,11 @@ function formatLine(line) { if (token != null) { line = line.replace(token, '$1'); } - line = addLink(line); line = addBold(line); line = addItalic(line); + line = addStrike(line); line = addTableLine(line); + line = addLink(line, listLink); line = addMono(line, listMono); elem.innerHTML = line; if (elem.getElementsByClassName('tablerow').length > 0) { @@ -471,11 +472,33 @@ function removeLink(line) { return [line, null]; } - line = line.replace(/(\[([^\]]*?)\]\(([^\)]*?)\))/g, "[$2]()"); + line = line.replace(/(\[([^\]]*?)\]\(([^\)]*?)\))/g, "[]()"); return [line, listLink.reverse()]; } -function addLink(line) { +function addLink(line, listLink) { + if (listLink == null) { + return line; + } + let cpt = 0; + let match; + let matches = []; + let re = /\[\]\(\)/g; + while ((match = re.exec(line)) != null) { + matches[cpt] = match.index; + if (cpt > 1000) { + continue; + } + cpt++; + } + matches = matches.reverse(); + for(let i=0; i[$2]($3)'); line = line.replace(/(\[([^\]]+?)\]\(\))/ig, '[$2]()'); line = line.replace(/(\[\]\(([^\)]+?)\))/ig, '[]($2)'); @@ -494,4 +517,9 @@ function addItalic(line) { return line; } +function addStrike(line) { + line = line.replace(/~~([^\s].*?)~~/ig, '~~$1~~'); + return line; +} + export { load, save, formatLine, formatTable, redrawTables, dpwidth, appendData }; diff --git a/templates/page.html b/templates/page.html index ed782f0..5cbf129 100644 --- a/templates/page.html +++ b/templates/page.html @@ -12,7 +12,7 @@ -
+