Skip to content

Commit 0e225c7

Browse files
committed
update
Signed-off-by: George Lemon <georgelemon@protonmail.com>
1 parent a43effa commit 0e225c7

File tree

2 files changed

+46
-32
lines changed

2 files changed

+46
-32
lines changed

src/marvdown/lexer.nim

Lines changed: 27 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -139,27 +139,30 @@ proc scanTextWithLinks(lex: var MarkdownLexer, wsno: int): seq[MarkdownTokenTupl
139139
tokens.add(newTokenTuple(lex, mtkText, buf, wsno=wsno))
140140
return tokens
141141

142+
const newSpace = " "
142143
proc nextToken*(lex: var MarkdownLexer): MarkdownTokenTuple =
143144
## Lex the next token from the input
144145
# Remove local wsno, use lex.wsno
145146
# Skip whitespace and newlines before token
146-
while true:
147-
# Only normalize line endings and consume newlines; leave spaces/tabs
148-
# so that they can be emitted as text tokens (preserve inline spaces).
149-
if lex.current == '\n':
150-
lex.col = 0
151-
lex.advance()
152-
continue
153-
elif lex.current == '\r':
154-
if lex.peek() == '\n':
155-
lex.advance()
156-
inc lex.line
147+
var newlineCount = 0
148+
while lex.current == '\n' or lex.current == '\r':
149+
# CRLF -> consume both as a single newline
150+
if lex.current == '\r' and lex.peek() == '\n':
151+
lex.advance() # consume '\r', now at '\n'
152+
# consume the newline character
153+
if lex.current == '\n' or lex.current == '\r':
154+
inc newlineCount
157155
lex.col = 0
158156
lex.advance()
159157
continue
160158
break
161-
# End of input
159+
160+
if newlineCount > 2:
161+
# More than 2 newlines -> paragraph break
162+
return newTokenTuple(lex, mtkParagraph, wsno=lex.wsno)
163+
162164
if lex.current == '\0':
165+
# End of input
163166
return newTokenTuple(lex, mtkEOF, wsno=lex.wsno)
164167

165168
# Return buffered tokens if present
@@ -445,9 +448,8 @@ proc nextToken*(lex: var MarkdownLexer): MarkdownTokenTuple =
445448
lex.advance()
446449
return newTokenTuple(lex, mtkLineBreak, wsno=lex.wsno)
447450
else:
448-
var text = " "
449451
lex.advance()
450-
return newTokenTuple(lex, mtkText, text, wsno=lex.wsno)
452+
return newTokenTuple(lex, mtkText, newSpace, wsno=lex.wsno)
451453
of '\t':
452454
# Treat tabs as text tokens similar to spaces.
453455
var text = "\t"
@@ -512,16 +514,21 @@ proc nextToken*(lex: var MarkdownLexer): MarkdownTokenTuple =
512514
lex.advance()
513515
return newTokenTuple(lex, mtkHtml, htmlContent, wsno=lex.wsno, attrs=some(@[tag]))
514516
of '|':
515-
# Table row
516-
lex.strbuf.setLen(0)
517-
while lex.current notin {'\n', '\r', '\0'}:
518-
lex.strbuf.add(lex.current)
517+
if lex.col == 0 or lex.wsno > 0:
518+
# table row
519+
lex.strbuf.setLen(0)
520+
while lex.current notin {'\n', '\r', '\0'}:
521+
lex.strbuf.add(lex.current)
522+
lex.advance()
523+
return newTokenTuple(lex, mtkTable, lex.strbuf, wsno=lex.wsno)
524+
else:
525+
# treat as text
519526
lex.advance()
520-
return newTokenTuple(lex, mtkTable, lex.strbuf, wsno=lex.wsno)
527+
return newTokenTuple(lex, mtkText, "|", wsno=lex.wsno)
521528
else:
522529
# Paragraph or plain text
523530
# Scan for auto links anywhere in the text
524-
let tokens = lex.scanTextWithLinks(lex.wsno)
531+
let tokens = lex.scanTextWithLinks(lex.wsno) # This should be optional, no?
525532
if tokens.len > 0:
526533
if tokens.len > 1:
527534
lex.pendingTokens = tokens[1..^1]

src/marvdown/parser.nim

Lines changed: 19 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -474,8 +474,8 @@ proc newParagraph*(curr: MarkdownTokenTuple): MarkdownNode =
474474
MarkdownNode(
475475
kind: mdkParagraph,
476476
children: MarkdownNodeList(),
477-
line: 0,
478-
wsno: 0
477+
line: curr.line,
478+
wsno: curr.wsno
479479
)
480480

481481
template withCurrentParagraph(body: untyped): untyped =
@@ -535,15 +535,23 @@ proc parseMarkdown(md: var Markdown, currentParagraph: var MarkdownNode) =
535535
let curr = md.parser.curr
536536
case curr.kind
537537
of mtkText:
538-
if currentParagraph.isNil:
539-
currentParagraph = newParagraph(curr)
540-
elif curr.col == 0:
541-
if md.ast.len > 0 and curr.line - currentParagraph.line > 1:
542-
# New paragraph after blank line
543-
closeCurrentParagraph() # Flush existing paragraph
544-
currentParagraph = newParagraph(curr)
545-
let textNode = md.parseText()
546-
currentParagraph.children.items.add(textNode)
538+
withCurrentParagraph do:
539+
let textNode = md.parseText()
540+
currentParagraph.children.items.add(textNode)
541+
md.advance()
542+
of mtkLineBreak:
543+
# Hard line break: add <br> inside the current paragraph
544+
withCurrentParagraph do:
545+
currentParagraph.children.items.add(MarkdownNode(
546+
kind: mdkHtml,
547+
html: "<br>",
548+
line: curr.line,
549+
wsno: curr.wsno
550+
))
551+
md.advance()
552+
of mtkParagraph:
553+
# Blank line / paragraph separator: close current paragraph
554+
closeCurrentParagraph()
547555
md.advance()
548556
of mtkImage:
549557
closeCurrentParagraph()
@@ -576,7 +584,6 @@ proc parseMarkdown(md: var Markdown, currentParagraph: var MarkdownNode) =
576584
line: curr.line,
577585
wsno: curr.wsno
578586
)
579-
580587
# parse inline content of the heading
581588
for n in md.parseInline(text):
582589
headingNode.children.items.add(n)

0 commit comments

Comments
 (0)