@ -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 ( '&' , '&' ) ;
line = line . replace ( '<' , '<' ) ;
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 } ;