Skip to content

Commit c2272ed

Browse files
committed
code block parsing
1 parent 14c1661 commit c2272ed

File tree

4 files changed

+43
-10
lines changed

4 files changed

+43
-10
lines changed

src/Markdown.hs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -91,8 +91,7 @@ titleAttr title = if T.null title then T.pack "" else T.concat [T.pack " title=\
9191

9292
escapeHtml :: Text -> Text
9393
escapeHtml =
94-
T.replace (T.pack "&") (T.pack "&")
95-
. T.replace (T.pack "<") (T.pack "&lt;")
94+
T.replace (T.pack "<") (T.pack "&lt;")
9695
. T.replace (T.pack ">") (T.pack "&gt;")
9796
. T.replace (T.pack "\"") (T.pack "&quot;")
9897

src/Parser.hs

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -114,6 +114,9 @@ parseMarkdown = parseLines [] . skipEmptyLines
114114
parseLines :: [Text] -> [Text] -> [MDElement]
115115
parseLines acc [] = processBlock (reverse acc)
116116
parseLines acc (line : lines)
117+
| isCodeBlockStart line =
118+
let (codeBlock, rest) = parseCodeBlock (line : lines)
119+
in processBlock (reverse acc) ++ [codeBlock] ++ parseLines [] rest
117120
| isTableLine line =
118121
case identifyTable (line : lines) of
119122
Just (tableLines, rest) ->
@@ -359,6 +362,7 @@ parseInline text
359362
| T.null text = []
360363
| otherwise =
361364
case T.uncons text of
365+
Just ('`', _) -> parseInlineCode text
362366
Just ('[', _) -> parseLinkOrCheckbox text
363367
Just ('*', _) -> parseDecoration '*' text
364368
Just ('_', _) -> parseDecoration '_' text
@@ -516,3 +520,29 @@ parsePlainText :: Text -> [MDElement]
516520
parsePlainText text =
517521
let (content, rest) = T.break (`elem` ['*', '_', '~', '<']) text
518522
in PlainText content : parseInline rest
523+
524+
isCodeBlockStart :: Text -> Bool
525+
isCodeBlockStart line =
526+
T.isPrefixOf (T.pack "```") (T.stripStart line)
527+
528+
parseCodeBlock :: [Text] -> (MDElement, [Text])
529+
parseCodeBlock (firstLine : rest) =
530+
let lang = T.strip $ T.drop 3 $ T.stripStart firstLine
531+
(codeLines, remainingLines) = span (not . isCodeBlockStart) rest
532+
codeBlockContent = T.unlines codeLines
533+
in (CodeBlock codeBlockContent, drop 1 remainingLines)
534+
parseCodeBlock _ = (CodeBlock T.empty, [])
535+
536+
parseInlineCode :: Text -> [MDElement]
537+
parseInlineCode text
538+
| T.isPrefixOf (T.pack "``") text =
539+
let (content, rest) = T.breakOn (T.pack "``") (T.drop 2 text)
540+
in if T.isPrefixOf (T.pack "``") rest
541+
then InlineCode (T.strip content) : parseInline (T.drop 2 rest)
542+
else PlainText (T.pack "``") : parseInline (T.drop 2 text)
543+
| T.isPrefixOf (T.pack "`") text =
544+
let (content, rest) = T.breakOn (T.pack "`") (T.drop 1 text)
545+
in if T.isPrefixOf (T.pack "`") rest
546+
then InlineCode (T.strip content) : parseInline (T.drop 1 rest)
547+
else PlainText (T.pack "`") : parseInline (T.drop 1 text)
548+
| otherwise = [PlainText text]

src/Types.hs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -27,12 +27,12 @@ data MDElement
2727
| Link
2828
{ linkText :: Text,
2929
linkUrl :: Text,
30-
linkTitle :: Maybe Text -- Optional title attribute
30+
linkTitle :: Maybe Text
3131
}
3232
| Image Text Text Text
3333
| UnorderedList [MDElement]
3434
| OrderedList [MDElement]
35-
| ListItem MDElement [MDElement] -- New type to support nested lists
35+
| ListItem MDElement [MDElement]
3636
| CodeBlock Text
3737
| InlineCode Text
3838
| Checkbox Bool [MDElement]

test/output.html

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -204,12 +204,16 @@ <h2 id="9f9a76a951506992fc919b8ae3f5ae15">Заголовок второго ур
204204
alt="Изображение title="Логотип Markdown"" />
205205
</p>
206206
<p>Функция `print (x)` выводит содержимое переменной ```x```.</p>
207-
<p>```</p>
208-
<h1 id="967f745ae03431977fb89c965c02c00c">
209-
include <a href="stdio.h">stdio.h</a>
210-
</h1>
211-
<p>int main() { printf(&amp;quot;Hello, World!&amp;quot;); return 0; } ```</p>
212-
<p>```javascript let x = 12; let y = 6; console.log(x + y); ```</p>
207+
<pre><code>#include &lt;stdio.h&gt;
208+
int main() {
209+
printf(&quot;Hello, World!&quot;);
210+
return 0;
211+
}
212+
</code></pre>
213+
<pre><code>let x = 12;
214+
let y = 6;
215+
console.log(x + y);
216+
</code></pre>
213217
<table>
214218
<thead>
215219
<tr>

0 commit comments

Comments
 (0)