more work on Markdown parsing, now with ordered lists

This commit is contained in:
HF 2021-11-27 03:10:30 +01:00
parent 554c67229f
commit d91bfeb527
2 changed files with 81 additions and 123 deletions

View File

@ -15,25 +15,21 @@ export default class MarkdownParser {
this.parseLinks = opt && opt.parseLinks || false;
this.tabWidth = opt && opt.tabWidth || 4;
this.newlineBreaksArticles = opt && opt.newlineBreaksArticles || true;
this.keepQuoteArrows = opt && opt.keepQuoteArrows || true;
}
parse(text: string) {
return this.parseText(text, 0, 0, '')[0];
return this.parseText(text, 0, 0)[0];
}
parseText(text, headingLevel, start, quoteLevel) {
parseText(text, headingLevel, start) {
let mdArray = [];
let iter = start;
while (iter < text.length) {
const [aMdArray, newIter, breaking] = this.parseSection(
text, iter, headingLevel, quoteLevel,
const [aMdArray, newIter] = this.parseSection(
text, iter, headingLevel,
);
iter = newIter;
mdArray = mdArray.concat(aMdArray);
if (breaking) {
break;
}
// either heading hit or article end
const chr = text[iter];
if (chr === '#') {
@ -53,18 +49,11 @@ export default class MarkdownParser {
const title = text.slice(iter + subLvl, lineEnd).trimLeft();
subLvl = Math.min(subLvl, 6);
const [subMdArray, newIter] = this.parseText(
text, subLvl, lineEnd + 1, quoteLevel,
text, subLvl, lineEnd + 1,
);
mdArray.push(['a', subLvl, title, subMdArray]);
iter = newIter;
}
} else if (chr === '>' || chr === '<') {
// child quote
const [subMdArray, newIter] = this.parseText(
text, 0, iter - quoteLevel.length, quoteLevel + chr,
);
mdArray.push([chr, subMdArray]);
iter = newIter;
} else {
break;
}
@ -97,26 +86,15 @@ export default class MarkdownParser {
text: string,
start: number,
headingLevel = 0,
quoteLevel = '',
indent = 0,
) {
let iter = start;
/*
* breaking is currently only used when
* end of quote block is reached
*/
let breaking = false;
const mdArray = [];
let paraStart = iter;
let lineNr = 0;
const addParagraph = (start, end) => {
let paraText = text.slice(start, end);
if (!this.keepQuoteArrows && quoteLevel) {
paraText = paraText.split('\n')
.map((t) => t.trim().slice(quoteLevel.length))
.join('\n');
}
mdArray.push(['p', paraText]);
}
@ -131,32 +109,6 @@ export default class MarkdownParser {
const paraLineStart = iter;
lineNr += 1;
/*
* break when in or out of quote levels
*/
if (!indent || lineNr > 1) {
if (text.startsWith(quoteLevel, iter)) {
iter += quoteLevel.length;
const chr = text[iter];
if (chr === '>' || chr === '<') {
if (iter - 1 > paraStart) {
addParagraph(paraStart, iter - quoteLevel.length - 1);
}
break;
}
}
else {
// quote ended aka less deep quotelevel
if (iter - 1 > paraStart) {
addParagraph(paraStart, iter - 1);
}
breaking = true;
break;
}
} else {
iter += quoteLevel.length;
}
/*
* act on indent
*/
@ -172,29 +124,62 @@ export default class MarkdownParser {
const chr = text[iter];
/*
* unordered list
*/
let isUnorderedList = false;
let isOrderedList = false;
if (chr === '-') {
isUnorderedList = true;
iter += 1;
}
/*
* ordered list
*/
if (!Number.isNaN(parseInt(chr))) {
let itern = iter + 1;
for(;!Number.isNaN(parseInt(text[itern])); itern += 1){}
if (text[itern] === '.' || text[itern] === ')') {
isOrderedList = true;
iter = itern + 1;
}
}
if (isUnorderedList || isOrderedList) {
if (paraLineStart - 1 > paraStart) {
addParagraph(paraStart, paraLineStart - 1);
}
let childMdArray;
[childMdArray, iter, breaking] = this.parseSection(
[childMdArray, iter] = this.parseSection(
text,
iter + 1,
iter,
headingLevel,
quoteLevel,
curIndent + 1,
);
childMdArray = ['-', childMdArray];
// lists are encapsuled by 'ul'
if (!mdArray.length || mdArray[mdArray.length - 1][0] !== 'ul') {
mdArray.push(['ul', [childMdArray]]);
// lists are encapsuled
const capsule = (isUnorderedList) ? 'ul' : 'ol';
if (!mdArray.length || mdArray[mdArray.length - 1][0] !== capsule) {
mdArray.push([capsule, [childMdArray]]);
}
else {
mdArray[mdArray.length - 1][1].push(childMdArray);
}
if (breaking) {
return [mdArray, iter, breaking];
paraStart = iter;
continue;
}
/*
* quotes
*/
if (chr === '>' || chr === '<') {
if (paraLineStart - 1 > paraStart) {
addParagraph(paraStart, paraLineStart - 1);
}
const [qArray, newIter] = this.parseQuote(text, iter);
mdArray.push(qArray);
iter = newIter;
paraStart = iter;
continue;
}
@ -239,12 +224,7 @@ export default class MarkdownParser {
iter += 1;
}
return [mdArray, iter, breaking];
}
parseList(text: string, start: number) {
const iter = start;
const mdArray = [];
return [mdArray, iter];
}
/*
@ -276,8 +256,11 @@ export default class MarkdownParser {
* we just parse till the ending occures
*/
parseCodeBlock(text, start) {
const cbStart = this.skipSpaces(text, start, true);
let iter = cbStart;
let iter = this.skipSpaces(text, start, false);
if (text[iter] === '\n') {
iter += 1;
}
const cbStart = iter;
while (true) {
if (iter >= text.length) {
return [['cb', text.slice(cbStart)], iter];
@ -294,6 +277,27 @@ export default class MarkdownParser {
}
}
/*
* parse quote
*/
parseQuote(text, start) {
// either '<' or '>'
const quoteChar = text[start];
let iter = start;
let quoteText = '';
while(true) {
if (iter >= text.length || text[iter] !== quoteChar) {
break;
}
iter += 1;
const startLine = iter;
for (;iter < text.length && text[iter] !== '\n'; iter += 1) {}
iter += 1;
quoteText += text.slice(startLine, iter);
}
return [[quoteChar, this.parseText(quoteText, 0, 0)[0]], iter];
}
skipSpaces(text: string, start: number, skipNewlines = false) {
let iter = start;
for (;iter < text.length; iter += 1) {
@ -304,58 +308,4 @@ export default class MarkdownParser {
}
return iter;
}
parseIndents(text: string) {
const lines = text.split('\n');
const indents = [];
const { tabWidth } = this;
/*
* Get indentation of lines
* @param text: string of text to parse
* @return [indents, lines]:
* indents: Array of normalized numerical indents
* lines: Array of trimmed lines
*/
for (let i = 0; i < lines.length; i += 1) {
const line = lines[i];
let indent = 0;
for (let c = 0; c < line.length; c += 1) {
const chr = line[c];
if (chr === '\t') {
indent += this.tabWidth;
} else if (chr === ' ') {
indent += 1;
} else {
break;
}
}
lines[i] = line.trim();
indents.push(indent);
}
// normalize
let min = indents[0];
let max = indents[0];
for (let m = 0; m < indents.length; m += 1) {
const indent = indents[m];
if (indent < min) min = indent;
if (indent > max) max = indent;
}
let cnt = 0;
console.log(min, max);
for (let n = min; n <= max; n += 1) {
let available = false;
for (let c = 0; c < indents.length; c += 1) {
if (indents[c] === n) {
if (!available) available = true;
indents[c] = cnt;
}
}
if (available) cnt += 1;
}
console.log(lines);
console.log(indents);
}
}

View File

@ -70,6 +70,14 @@ const Markdown = ({ mdArray }) => {
</ul>
);
}
case 'ol': {
const children = part[1];
return (
<ol>
<Markdown mdArray={children} />
</ol>
);
}
case '-': {
const children = part[1];
return (