implémentation partielle des tableaux

pull/1/head
Nicolas Sanchez 3 years ago
parent 6d9f610209
commit e7e48bcdcc

1
Cargo.lock generated

@ -847,6 +847,7 @@ dependencies = [
"askama_actix",
"clap",
"git2",
"regex",
"serde",
"serde_json",
]

@ -18,3 +18,5 @@ serde = { version = "1.0", features = ["derive"] }
serde_json = "1.0"
git2 = "0.16.0"
regex = "1"

@ -13,3 +13,17 @@ https://stackoverflow.com/questions/6249095/how-to-set-the-caret-cursor-position
|: OR
:: Match a colon
(?:$|\S): Match end or a non-whitespace
Javascript Mutex.mutex()
## traiter le copier/coller
editor.addEventListener("paste", function(e) {
// cancel paste
e.preventDefault();
// get text representation of clipboard
var text = (e.originalEvent || e).clipboardData.getData('text/plain');
// insert text manually
document.execCommand("insertHTML", false, text);
});

@ -0,0 +1,38 @@
# RustyNotes
L'objectif de RustyNotes 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.
> Pour réinitialiser la page, il suffit de la recharger.
## Utilisation
Pour passer en mode édition, il suffit de cliquer sur le texte à modifier.
Un appui sur la touche `ESC` permet de repasser en mode affichage.
L'enregistrement est automatique dès que l'on sort du mode édition ou après 5 secondes sans modifications.
## Syntaxe
### Titres
Il y a 4 niveaux de titres :
- `# titre 1`
- `## titre 2`
- `### titre 3`
- `#### titre 4`
### Liens
Pour une url longue à laquelle on veut associer un libellé plus parlant, on choisira la syntaxe complète :
- [Wikipedia Markdown](https://fr.wikipedia.org/wiki/Markdown)
Si on veut que le libellé corresponde à l'url, on pourra utiliser l'une des syntaxes suivantes :
- [](https://www.google.fr)
- [index]()
> **A noter :** Les url du type `protocole://` s'ouvriront dans un nouvel onglet, tandis que les url pointant sur des pages internes s'ouvriront par défaut dans l'onglet actuel.
### Listes
#### Liste à puces
Les listes à puces peuvent avoir trois niveaux. On peut utiliser indifféremment `-`, `*` ou `+`.
- élément de liste de niveau 1
- + élément de liste de niveau 2
- - - élément de liste de niveau 3
#### Listes numérotées
A l'instar des listes à puces, les listes numérotées peuvent avoir trois niveaux.
La numérotation n'est pas automatique.
1. premier élément
2. deuxième élément
2.1. premier élément de deuxième niveau niveau
2.2. second élément de deuxième niveau
3. troisième niveau
3.1. élément 3.1.
3.1.1. élément 3.1.1.

@ -0,0 +1,8 @@
# Les poissons osseux
## Qui sont-ils ?
## Les différentes parties du poisson
## De toutes les tailles et de toutes les couleurs
## Où vivent-ils ?
## Comment respirent-ils ?
## Que mangent-ils ?
## Comment se reproduisent-ils ?

@ -1,5 +1,5 @@
use actix_web::web;
use actix_web::{HttpResponse, Responder, get};
use actix_web::{Responder, get};
use askama_actix::Template;
use askama_actix::TemplateToResponse;
@ -8,12 +8,12 @@ use crate::commons::AppData;
#[derive(Template)]
#[template(path = "index.html")]
pub struct IndexTemplate {
pub struct PageTemplate {
pub name: String,
}
#[get("/")]
async fn index(data: web::Data<AppData>) -> impl Responder {
let name = data.name.to_owned();
IndexTemplate { name }.to_response()
PageTemplate { name }.to_response()
}

@ -1,2 +1,3 @@
pub mod page;
pub mod index;
pub mod commons;

@ -1,8 +1,8 @@
use actix_web::{post, web, App, HttpResponse, HttpServer, Responder};
use actix_web::{web, App, HttpServer};
use actix_files;
use mdnotes::commons::{Arguments, AppData};
use mdnotes::index;
use mdnotes::{ page, index };
#[actix_web::main]
async fn main() -> std::io::Result<()> {
@ -20,6 +20,8 @@ async fn main() -> std::io::Result<()> {
App::new()
.app_data(web::Data::new(appdata.to_owned()))
.service(index::index)
.service(page::page)
//.service(page::page_link)
.service(actix_files::Files::new("/static", "./static"))
.service(actix_files::Files::new("/static/modules", "./static/modules"))
})

@ -0,0 +1,58 @@
use actix_web::web;
use actix_web::{Responder, get};
use std::fs;
//use regex::Regex;
use askama_actix::Template;
use askama_actix::TemplateToResponse;
use crate::commons::AppData;
#[derive(Template)]
#[template(path = "page.html")]
pub struct PageTemplate {
pub name: String,
pub md: String,
pub init: String,
}
#[get("/page/{page}")]
async fn page(path: web::Path<(String,)>, data: web::Data<AppData>) -> impl Responder {
let pagename = &path.0;
let name = data.name.to_owned() + " " + pagename.as_str();
let filename = String::from("pages/") + pagename.as_str() + ".md";
let md = match fs::read_to_string(filename) {
Ok(txt) => txt,
Err(_) => String::from("# Nouvelle page"),
};
let init = String::from("init();");
PageTemplate { name, md, init }.to_response()
}
/*#[get("/page/{oldpage}/{page}")]
async fn page_link(path: web::Path<(String, String,)>, data: web::Data<AppData>) -> impl Responder {
let pagename = &path.1;
let name = data.name.to_owned() + " " + pagename.as_str();
let filename = String::from("pages/") + pagename.as_str() + ".md";
let md = match fs::read_to_string(filename) {
Ok(txt) => txt,
Err(_) => String::from("# Nouvelle page"),
};
let init = format!("init('{}')", pagename);
PageTemplate { name, md, init }.to_response()
}*/
/*fn normalize_pagename(pagename: String) -> Result<String, ()> {
let pagename = pagename.trim();
let space_re = Regex::new(r"[-\s]").unwrap();
let pagename = &*space_re.replace_all(pagename, "_");
let re = Regex::new(r"").unwrap();
if re.is_match(pagename) {
Ok(pagename.to_owned())
} else {
Err(())
}
}*/

@ -7,6 +7,11 @@ body {
margin: 0;
}
button {
width: 2.2rem;
height: 2.2rem;
}
textarea#ta {
display: none;
width: 100%;
@ -22,34 +27,43 @@ div#mdnotes {
padding-right: 3rem;
padding-bottom: 1rem;
background-color: #ffffff;
min-height: 90%;
}
div#mdnotes:focus {
outline: none;
}
div#mdnotes div.line {
border-bottom: 1px solid #dddddd;
padding-top: 0rem;
margin-top: 0rem;
font-size: 8pt;
}
div#mdnotes div.h1 {
font-size: 3rem;
margin-top: 1rem;
margin-top: 1.5rem;
margin-bottom: 1.3rem;
padding-bottom: 0.5rem;
border-bottom: 1px solid #dddddd;
}
div#mdnotes div.h2 {
font-size: 2.2rem;
margin-top: 0.5rem;
font-size: 2.3rem;
margin-top: 1rem;
margin-bottom: 1rem;
}
div#mdnotes div.h3 {
font-size: 1.5rem;
margin-top: 0.5rem;
margin-bottom: 1rem;
font-size: 1.8rem;
margin-top: 0.8rem;
margin-bottom: 0.8rem;
}
div#mdnotes div.h4 {
font-style: italic;
font-size: 1.4rem;
margin-top: 0.5rem;
margin-bottom: 0.5rem;
}
@ -78,40 +92,79 @@ div#mdnotes div.bq3 {
border-left: .9rem solid #6688bb;
}
div#mdnotes div.ul1 { padding-left: 2.2rem; }
div#mdnotes div.ul1 { display:list-item; list-style-position: inside; padding-left: 2.2rem; padding-bottom: .2rem; padding-top: .2rem; }
div#mdnotes div.ul1.bq1 { padding-left: 1.9rem; }
div#mdnotes div.ul1.bq2 { padding-left: 1.6rem; }
div#mdnotes div.ul1.bq3 { padding-left: 1.3rem; }
div#mdnotes div.ul2 { padding-left: 2.7rem; }
div#mdnotes div.ul2 { display:list-item; list-style-position: inside; padding-left: 2.7rem; padding-bottom: .2rem; padding-top: .2rem; }
div#mdnotes div.ul2.bq1 { padding-left: 2.4rem; }
div#mdnotes div.ul2.bq2 { padding-left: 2.1rem; }
div#mdnotes div.ul2.bq3 { padding-left: 1.8rem; }
div#mdnotes div.ul3 { padding-left: 3.2rem; }
div#mdnotes div.ul3 { display:list-item; list-style-position: inside; padding-left: 3.2rem; padding-bottom: .2rem; padding-top: .2rem; }
div#mdnotes div.ul3.bq1 { padding-left: 2.9rem; }
div#mdnotes div.ul3.bq2 { padding-left: 2.6rem; }
div#mdnotes div.ul3.bq3 { padding-left: 2.3rem; }
div#mdnotes div.ol1 { padding-left: 2.2rem; }
div#mdnotes div.ol1 { padding-left: 2.2rem; padding-bottom: .2rem; padding-top: .2rem; }
div#mdnotes div.ol1.bq1 { padding-left: 1.9rem; }
div#mdnotes div.ol1.bq2 { padding-left: 1.6rem; }
div#mdnotes div.ol1.bq3 { padding-left: 1.3rem; }
div#mdnotes div.ol2 { padding-left: 2.7rem; }
div#mdnotes div.ol2 { padding-left: 2.7rem; padding-bottom: .2rem; padding-top: .2rem; }
div#mdnotes div.ol2.bq1 { padding-left: 2.4rem; }
div#mdnotes div.ol2.bq2 { padding-left: 2.1rem; }
div#mdnotes div.ol2.bq3 { padding-left: 1.8rem; }
div#mdnotes div.ol3 { padding-left: 3.2rem; }
div#mdnotes div.ol3 { padding-left: 3.2rem; padding-bottom: .2rem; padding-top: .2rem; }
div#mdnotes div.ol3.bq1 { padding-left: 2.9rem; }
div#mdnotes div.ol3.bq2 { padding-left: 2.6rem; }
div#mdnotes div.ol3.bq3 { padding-left: 2.3rem; }
div#mdnotes div.tablecell {
div#mdnotes span.oltoken {
display: inline-block;
width: 2rem;
}
div#mdnotes span.lefttablespacer {
display: inline-block;
}
div#mdnotes span.righttablespacer {
display: inline-block;
}
div#mdnotes div.tablerow {
margin-top: .5rem;
margin-bottom: .9rem;
}
div#mdnotes span.tablerow {
border-bottom: 1px solid #dddddd;
padding-bottom: 0.4rem;
}
div#mdnotes div.firsttablerow {
margin-top: 1.5rem;
}
div#mdnotes div.firsttablerow span.tablerow {
margin-bottom: 1.5rem;
border-bottom: 1px solid #666666;
font-weight: bold;
}
div#mdnotes div.lasttablerow {
margin-bottom: 1.5rem;
}
div#mdnotes div.lasttablerow span.tablerow {
margin-bottom: 1.5rem;
border-bottom: none;
}
div#mdnotes div.mdnotes_line span.token {
font-weight: 1;
color: #1353b3;

@ -1,11 +1,19 @@
function load(textarea, div) {
div.innerHTML = '';
let lines = textarea.value.split('\n');
let firsttableline = null;
for (let i = 0; i < lines.length; i++) {
let line = lines[i];
line = line.replace(/\t/, emsp());
let elem = formatLine(line);
div.append(elem);
if (elem.classList.contains('tablerow')) {
if (firsttableline == null) {
firsttableline = elem;
}
} else if (firsttableline != null) {
formatTable(firsttableline);
firsttableline = null;
}
}
}
@ -13,7 +21,12 @@ function save(textarea, div) {
let lines = div.children;
let text = '';
for (let i=0; i<lines.length; i++) {
text += lines[i].innerText.replace(emsp(), '\t') + '\n';
if (lines[i].innerText != '\n') {
text += lines[i].innerText.replace(emsp(), '\t');
}
if (i < lines.length - 1) {
text += '\n';
}
}
textarea.value = text;
}
@ -56,71 +69,100 @@ function onlinkout(e) {
function formatLine(line) {
let token = null;
let elem = document.createElement('div');
elem.classList.add('mdnotes_line');
if (line == '' || line == '\n') {
elem.classList.add('body');
elem.innerHTML = '<br>';
return elem;
}
line = line.replace(/\t/, emsp());
line = line.replace('&', '&amp;');
line = line.replace('<', '&lt;');
if (line.match(/^\s*####\s/i)) {
token = /^(\s*####\s)/i;
let ret = removeMono(line);
line = ret[0];
let listMono = ret[1];
if (line.match(/^\s*-{3,}\s*$/)) {
token = /^(\s*-{3,}\s*)$/
elem.classList.add('line');
} else if (line.match(/^\s*####(\s|$)/i)) {
token = /^(\s*####(\s|$))/i;
elem.classList.add('h4');
} else if (line.match(/^\s*###\s/i)) {
token = /^(\s*###\s)/i;
} else if (line.match(/^\s*###(\s|$)/i)) {
token = /^(\s*###(\s|$))/i;
elem.classList.add('h3');
} else if (line.match(/^\s*##\s/)) {
token = /^(\s*##\s)/i;
} else if (line.match(/^\s*##(\s|$)/)) {
token = /^(\s*##(\s|$))/i;
elem.classList.add('h2');
} else if (line.match(/^\s*#\s/i)) {
token = /^(\s*#\s)/i;
} else if (line.match(/^\s*#(\s|$)/i)) {
token = /^(\s*#(\s|$))/i;
elem.classList.add('h1');
} else if (line.match(/^\s*>\s*>\s*>\s/i)) {
token = /^(\s*>\s*>\s*>\s)/i;
} else if (line.match(/^\s*>\s*>\s*>(\s|$)/i)) {
token = /^(\s*>\s*>\s*>(\s|$))/i;
elem.classList.add('bq3');
elem.classList.add('bq');
} else if (line.match(/^\s*>\s*>\s/i)) {
token = /^(\s*>\s*>\s)/i;
} else if (line.match(/^\s*>\s*>(\s|$)/i)) {
token = /^(\s*>\s*>(\s|$))/i;
elem.classList.add('bq2');
elem.classList.add('bq');
} else if (line.match(/^\s*>\s/i)) {
token = /^(\s*>\s)/i;
} else if (line.match(/^\s*>(\s|$)/i)) {
token = /^(\s*>(\s|$))/i;
elem.classList.add('bq1');
elem.classList.add('bq');
} else {
elem.classList.add('body');
}
if (elem.classList.contains('bq') || elem.classList.contains('body')) {
if (line.match(/^\s*((>\s*){0,3}\s)?([\*\-+]\s*){3}\s/i)) {
token = /^(\s*(>\s*){0,3}([\*\-+]\s*){2})/i;
if (line.match(/^\s*((>\s*){0,3}\s)?([\*\-+]\s*){3}(\s|$)/i)) {
token = /^(\s*(>\s*){0,3}([\*\-+]\s*){3}(\s|$))/i;
elem.classList.add('ul3');
elem.classList.remove('body');
} else if (line.match(/^\s*((>\s*){0,3}\s)?([\*\-+]\s*){2}\s/i)) {
token = /^(\s*(>\s*){0,3}[\*\-+])/i;
} else if (line.match(/^\s*((>\s*){0,3}\s)?([\*\-+]\s*){2}(\s|$)/i)) {
token = /^(\s*(>\s*){0,3}([\*\-+]\s*){2}(\s|$))/i;
elem.classList.add('ul2');
elem.classList.remove('body');
} else if (line.match(/^\s*((>\s*){0,3}\s)?[\*\-+]\s/i)) {
token = /^(\s*(>\s*){0,3}\s*)/;
} else if (line.match(/^\s*((>\s*){0,3}\s)?[\*\-+](\s|$)/i)) {
token = /^(\s*(>\s*){0,3}[\*\-+](\s*|$))/;
elem.classList.add('ul1');
elem.classList.remove('body');
} else if (line.match(/^\s*((>\s*){0,3}\s)?([0-9]+\.){3}\s/i)) {
token = /^(\s*(>\s*){0,3}\s*)/;
} else if (line.match(/^\s*((>\s*){0,3}\s)?([0-9]+\.){3}(\s|$)/i)) {
token = /^(\s*(>\s*){0,3}(\s*|$))/;
elem.classList.add('ol3');
elem.classList.remove('body');
} else if (line.match(/^\s*((>\s*){0,3}\s)?([0-9]+\.){2}\s/i)) {
token = /^(\s*(>\s*){0,3}\s*)/;
} else if (line.match(/^\s*((>\s*){0,3}\s)?([0-9]+\.){2}(\s|$)/i)) {
token = /^(\s*(>\s*){0,3}(\s*|$))/;
elem.classList.add('ol2');
elem.classList.remove('body');
} else if (line.match(/^\s*((>\s*){0,3}\s)?[0-9]+\.\s/i)) {
token = /^(\s*(>\s*){0,3}\s*)/;
} else if (line.match(/^\s*((>\s*){0,3}\s)?[0-9]+\.(\s|$)/i)) {
token = /^(\s*(>\s*){0,3}(\s*|$))/;
elem.classList.add('ol1');
elem.classList.remove('body');
}
}
elem.classList.add('mdnotes_line');
line = addLink(line);
line = addBold(line);
line = addItalic(line);
line = addMono(line);
if (token != null) {
line = line.replace(token, '<span class="token">$1</span>');
}
line = addLink(line);
line = addBold(line);
line = addItalic(line);
line = addTableLine(line);
line = addMono(line, listMono);
elem.innerHTML = line;
if (elem.getElementsByClassName('tablerow').length > 0) {
if (elem.childNodes[0].childNodes.length > 0) {
let child = elem.childNodes[0].childNodes[0];
while(child != null) {
if (child.nodeType == 3) {
let newchild = document.createElement('span');
newchild.innerText = child.nodeValue;
child.parentNode.replaceChild(newchild, child);
child = newchild;
}
child = child.nextSibling;
}
}
elem.classList.remove('body');
elem.classList.add('tablerow');
}
let links = elem.getElementsByClassName('link');
for (let i=0; i<links.length; i++) {
let link = links[i];
@ -131,13 +173,157 @@ function formatLine(line) {
return elem;
}
function addMono(line) {
line = line.replace(/`(.*?)`/ig, '<span class="mono"><span class="token">`</span>$1<span class="token">`</span></span>');
function addTableLine(line) {
if (line.match(/^\s*\|(\s*.*?\|)*/)) {
let cpt = 0;
let re = /\|/g;
let match;
let matches = [];
while ((match = re.exec(line)) != null) {
matches[cpt] = match.index;
if (cpt > 1000) {
continue;
}
cpt++;
}
matches = matches.reverse();
for(let i=0; i<matches.length; i++) {
let index = matches[i];
if (i == matches.length - 1) {
// premier |
line = line.substring(0, index) + '<span class="token">|</span><span class="lefttablespacer"></span>' + line.substring(index+1, line.length);
continue;
}
if (i == 0 && index == line.length - 1) {
// dernier |
line = line.substring(0, index) + '<span class="righttablespacer"></span><span class="token">|</span>' + line.substring(index+1, line.length);
continue;
}
line = line.substring(0, index) + '<span class="righttablespacer"></span><span class="token">|</span><span class="lefttablespacer"></span>' + line.substring(index+1, line.length);
}
line = '<span class="tablerow">' + line + '</span>';
}
return line;
}
function formatTable(line) {
if (! line.classList.contains('tablerow')) {
return;
}
let firstline = line;
let lastline = line;
while (firstline.previousSibling !== null && firstline.previousSibling.classList.contains('tablerow')) {
firstline = firstline.previousSibling;
firstline.classList.remove('firsttablerow');
firstline.classList.remove('lasttablerow');
}
while (lastline.nextSibling !== null && lastline.nextSibling.classList.contains('tablerow')) {
lastline = lastline.nextSibling;
lastline.classList.remove('firsttablerow');
lastline.classList.remove('lasttablerow');
}
firstline.classList.add('firsttablerow');
lastline.classList.add('lasttablerow');
resizeTableCols(firstline, lastline)
}
function resizeTableCols(firstline, lastline) {
let colsmaxwidth = [];
let currentline = firstline;
while (currentline !== null && currentline.classList.contains('tablerow')) {
let tablerow = currentline.getElementsByClassName('tablerow')[0];
let childNodes = tablerow.childNodes;
let currentwidth = 0;
let col = 0;
let currentleft;
for(let i=0; i<childNodes.length; i++) {
let child = childNodes[i];
if (currentleft == null && child.classList != null && child.classList.contains('lefttablespacer')) {
currentleft = child;
} else {
if (child.classList != null && child.classList.contains('righttablespacer')) {
if (colsmaxwidth[col] == null || colsmaxwidth[col] < currentwidth) {
colsmaxwidth[col] = currentwidth;
}
child.dataWidth = currentwidth;
currentleft.dataWidth = currentwidth;
currentleft = null;
currentwidth = 0;
col += 1;
} else {
let width = child.getBoundingClientRect().width;
currentwidth += width;
}
}
}
currentline = currentline.nextSibling;
}
currentline = firstline;
while (currentline !== null && currentline.classList.contains('tablerow')) {
let tablerow = currentline.getElementsByClassName('tablerow')[0];
let childNodes = tablerow.childNodes;
let col = 0;
let currentleft;
for(let i=0; i<childNodes.length; i++) {
let child = childNodes[i];
if (currentleft == null && child.classList != null && child.classList.contains('lefttablespacer')) {
currentleft = child;
} else {
if (child.classList != null && child.classList.contains('righttablespacer')) {
let leftwidth = 10;
let rightwidth = Math.ceil(colsmaxwidth[col] - child.dataWidth) + 10;
currentleft.style.width = '' + leftwidth + 'px';
child.style.width = '' + rightwidth + 'px';
currentleft = null;
col += 1;
}
}
}
currentline = currentline.nextSibling;
}
}
function removeMono(line) {
let listMono = line.match(/`(`|.*?)`/g);
if (listMono == null) {
return [line, null];
}
line = line.replace(/`(`|.*?)`/g, "``");
return [line, listMono.reverse()];
}
function addMono(line, listMono) {
if (listMono == 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<matches.length; i++) {
let mono = listMono[i];
mono = mono.substring(1, mono.length - 1);
line = line.substring(0, matches[i]) + '<span class="token">`</span><span class="mono">' + mono + '</span><span class="token">`</span>' + line.substring(matches[i]+2, line.length);
}
return line;
}
function addLink(line) {
line = line.replace(/(\[(.*?)\]\((.*?)\))/ig, '<span class="token">[</span><a class="link" href="$3">$2</a><span class="token">]($3)</span>');
line = line.replace(/(\[([^\]]+?)\]\(([^\)]+?)\))/ig, '<span class="token">[</span><a class="link" data-href="$3" href="$3">$2</a><span class="token">]($3)</span>');
line = line.replace(/(\[([^\]]+?)\]\(\))/ig, '<span class="token">[</span><a class="link" data-href="$2" href="$2">$2</a><span class="token">]()</span>');
line = line.replace(/(\[\]\(([^\)]+?)\))/ig, '<span class="token">[](</span><a class="link" data-href="$2" href="$2">$2</a><span class="token">)</span>');
return line;
}
@ -153,4 +339,4 @@ function addItalic(line) {
return line;
}
export { load, save, formatLine };
export { load, save, formatLine, formatTable };

@ -1,5 +1,12 @@
import { getStartPositionInLine, setStartPositionInLine } from './position.js';
import { formatLine, load, save } from './md.js';
import { formatLine, load, save, formatTable } from './md.js';
function timeoutSave() {
if (window.tos !== null) {
window.clearTimeout(window.tos);
}
window.tos = window.setTimeout(onsave, 5000);
}
function ontextarea(e) {
let ta = document.getElementById('ta');
@ -19,17 +26,26 @@ function onload(e) {
}
function onedit(e) {
timeoutSave();
let ret = getStartPositionInLine();
let line = ret[0];
let position = ret[1];
if (line.innerText == '\n') {
line.className = 'mdnotes_line';
line.classList.add('body');
return;
}
let prevline = line.previousSibling;
if (prevline != null && prevline.innerText == '\n') {
prevline.className = 'mdnotes_line';
prevline.classList.add('body');
}
let newline = formatLine(line.innerText);
line.parentNode.replaceChild(newline, line);
formatTable(newline);
setStartPositionInLine(newline, position);
}
@ -49,27 +65,56 @@ function onkeydown(e) {
} else {
line.innerHTML = txt.substring(0, position) + key + txt.substring(position, txt.length);
}
/*if (line.innerText.match(RegExp(emsp()))) {
alert('emsp');
}*/
setStartPositionInLine(line, position + 1);
onedit(e);
return false;
}
function onkeypress(e) {
if (e.key == 'Escape') {
e.preventDefault();
document.getElementById('mdnotes').blur();
onsave();
return false;
}
if (e.key == 'Enter') {
}
}
function onkeyup(e) {
if (e.key == 'Escape') {
e.preventDefault();
document.getElementById('mdnotes').blur();
onsave();
return false;
}
}
function init() {
function onpaste(e) {
timeoutSave();
let data = e.clipboardData.getData('text/plain');
if (data.match(/ \w+:\/\/.*/i)) {
data = '[](' + data + ')';
e.clipBoard.setData('text/plain', data);
}
}
function oncopy(e) {
alert(e.clipboardData.getData('text/plain'));
}
function init(pagename = null) {
/*if (pagename != null) {
window.history.replaceState(null, '', '/page/' + pagename);
}*/
let mdnotesdiv = document.getElementById('mdnotes');
mdnotesdiv.addEventListener('input', onedit);
mdnotesdiv.addEventListener('keyup', onkeyup);
mdnotesdiv.addEventListener('keypress', onkeypress);
mdnotesdiv.addEventListener('keydown', onkeydown);
mdnotesdiv.addEventListener('paste', onpaste);
mdnotesdiv.addEventListener('copy', oncopy);
let saveButton = document.getElementById('saveButton');
saveButton.addEventListener('click', onsave);
loadButton.addEventListener('click', onload);
@ -78,4 +123,4 @@ function init() {
onload();
}
init();
export { init };

@ -8,24 +8,9 @@
<meta name="mobile-web-app-capable" content="yes">
<meta name="apple-mobile-web-app-status-bar-style" content="black">
<title>{{name}}</title>
<link rel="stylesheet" href="static/mdnotes.css">
<link rel="stylesheet" href="../static/mdnotes.css">
</head>
<body>
<div><button id="saveButton">Save</button><button id="loadButton">Load</button><button id="taButton">Textarea</button></div>
<textarea id="ta" class="mdnotes" style="display: none;">
# Titre 1
Un petit texte
## Titre 2
### Titre 3-1
Encore un joli texte
### Titre 3-2
T'en as marre ???
#### Titre 4
- coucou
- pas vrai
- tant pis
Moi oui !!!</textarea>
<div id="mdnotes" class="mdnotes" contenteditable="true"></div>
<script type="module" src="static/modules/mdnotes.js"></script>
<h1></h1>
</body>
</html>

@ -0,0 +1,24 @@
<html>
<head>
<meta name="viewport" content="target-densitydpi=device-dpi, width=device-width, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0, user-scalable=no, minimal-ui" />
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<meta http-equiv="Content-Language" content="fr">
<meta name="apple-mobile-web-app-capable" content="yes">
<meta name="mobile-web-app-capable" content="yes">
<meta name="apple-mobile-web-app-status-bar-style" content="black">
<title>{{name}}</title>
<link rel="stylesheet" href="/static/mdnotes.css">
<script type="module" src="/static/modules/mdnotes.js"></script>
</head>
<body>
<div><button id="saveButton">💾</button> <button id="loadButton">Load</button> <button id="taButton">📋</button></div>
<textarea id="ta" class="mdnotes" style="display: none;">{{md}}</textarea>
<div id="mdnotes" class="mdnotes" contenteditable="true" spellcheck="false"></div>
<script type="module">
import { init } from '/static/modules/mdnotes.js';
{{ init|safe }}
</script>
</body>
</html>
Loading…
Cancel
Save