Skip to content

Commit c6c9244

Browse files
committed
some links
1 parent 64b2863 commit c6c9244

File tree

4 files changed

+80
-15
lines changed

4 files changed

+80
-15
lines changed

src/Markdown.hs

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,19 @@ markdownToHtml input = T.concat $ map renderElement $ Parser.parseMarkdown $ T.l
1313

1414
renderElement :: MDElement -> Text
1515
renderElement element = case element of
16+
Link text url title ->
17+
let titleAttr = case title of
18+
Just t -> T.concat [T.pack " title=\"", escapeHtml t, T.pack "\""]
19+
Nothing -> T.pack ""
20+
in T.concat
21+
[ T.pack "<a href=\"",
22+
escapeHtml url,
23+
T.pack "\"",
24+
titleAttr,
25+
T.pack ">",
26+
escapeHtml text,
27+
T.pack "</a>"
28+
]
1629
Paragraph elements -> T.concat [T.pack "<p>", T.concat (map renderElement elements), T.pack "</p>\n"]
1730
LineBreak -> T.pack "<br />\n"
1831
Header level text id ->
@@ -24,7 +37,6 @@ renderElement element = case element of
2437
Strikethrough text -> T.concat [T.pack "<s>", escapeHtml text, T.pack "</s>"]
2538
Underlined text -> T.concat [T.pack "<u>", escapeHtml text, T.pack "</u>"]
2639
HorizontalRule -> T.pack "<hr />\n"
27-
Link text url -> T.concat [T.pack "<a href=\"", url, T.pack "\">", escapeHtml text, T.pack "</a>"]
2840
Image alt url title -> T.concat [T.pack "<img src=\"", url, T.pack "\" alt=\"", alt, T.pack "\"", titleAttr title, T.pack " />"]
2941
-- Updated list rendering to support nested lists and different markers
3042
UnorderedList items -> T.concat [T.pack "<ul>\n", T.concat (map renderListItem items), T.pack "</ul>\n"]

src/Parser.hs

Lines changed: 51 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -358,13 +358,63 @@ parseInline text
358358
| T.null text = []
359359
| otherwise =
360360
case T.uncons text of
361-
Just ('[', _) -> parseCheckbox text
361+
Just ('[', _) -> parseLinkOrCheckbox text
362362
Just ('*', _) -> parseDecoration '*' text
363363
Just ('_', _) -> parseDecoration '_' text
364364
Just ('~', _) -> parseStrikethrough text
365365
Just ('<', _) -> parseHtmlTags text
366366
_ -> parsePlainText text
367367

368+
parseLinkOrCheckbox :: Text -> [MDElement]
369+
parseLinkOrCheckbox text
370+
| T.isPrefixOf (T.pack "[x]") text || T.isPrefixOf (T.pack "[ ]") text =
371+
parseCheckbox text
372+
| T.isPrefixOf (T.pack "[") text =
373+
parseBracketLink text
374+
| otherwise = parsePlainText text
375+
376+
parseBracketLink :: Text -> [MDElement]
377+
parseBracketLink text =
378+
let linkTextStart = T.tail $ T.takeWhile (/= ']') text
379+
urlStart = T.drop 2 $ T.dropWhile (/= '(') text
380+
(linkUrl, rest) = T.break (== ')') urlStart
381+
cleanUrl = T.strip linkUrl
382+
383+
-- Check for optional title
384+
(titlePart, remainingText) =
385+
case T.uncons rest of
386+
Just (_, titleText) ->
387+
let stripped = T.strip $ T.takeWhile (/= ')') titleText
388+
titleRemaining = T.drop (T.length stripped + 1) titleText
389+
in if T.isPrefixOf (T.pack "\"") stripped && T.isSuffixOf (T.pack "\"") stripped
390+
then (Just (T.init $ T.tail stripped), titleRemaining)
391+
else (Nothing, rest)
392+
Nothing -> (Nothing, rest)
393+
394+
linkTextParsed = parseInline linkTextStart
395+
nextText = T.drop 1 remainingText
396+
in case linkTextParsed of
397+
[] -> Link cleanUrl cleanUrl Nothing : parseInline nextText
398+
[PlainText t] -> Link t cleanUrl titlePart : parseInline nextText
399+
multipleElems -> Link (T.concat $ map renderPlainText multipleElems) cleanUrl titlePart : parseInline nextText
400+
where
401+
renderPlainText (PlainText t) = t
402+
renderPlainText _ = T.empty
403+
404+
parseAngleBracketLink :: Text -> [MDElement]
405+
parseAngleBracketLink text =
406+
let (link, rest) = T.break (== '>') (T.tail text)
407+
cleanLink = T.strip link
408+
in Link cleanLink cleanLink Nothing : parseInline (T.drop 1 rest)
409+
410+
renderPlainText :: MDElement -> Text
411+
renderPlainText (PlainText t) = t
412+
renderPlainText (Bold t) = t
413+
renderPlainText (Italic t) = t
414+
renderPlainText (BoldItalic t) = t
415+
renderPlainText (Paragraph elems) = T.concat $ map renderPlainText elems
416+
renderPlainText _ = T.empty
417+
368418
parseCheckbox :: Text -> [MDElement]
369419
parseCheckbox text
370420
| T.isPrefixOf (T.pack "[x]") text || T.isPrefixOf (T.pack "[X]") text =

src/Types.hs

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,11 @@ data MDElement
2424
| Underlined Text
2525
| LineBreak
2626
| HorizontalRule
27-
| Link Text Text
27+
| Link
28+
{ linkText :: Text,
29+
linkUrl :: Text,
30+
linkTitle :: Maybe Text -- Optional title attribute
31+
}
2832
| Image Text Text Text
2933
| UnorderedList [MDElement]
3034
| OrderedList [MDElement]

test/output.html

Lines changed: 11 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -189,17 +189,16 @@ <h2 id="9f9a76a951506992fc919b8ae3f5ae15">Заголовок второго ур
189189
<li>Второй пункт</li>
190190
</ol>
191191
<p>&amp;lt;https://skillbox.ru/media/code/&amp;gt;</p>
192-
<p>[Skillbox Media](https://skillbox.ru/media/) без подсказки</p>
192+
<p><a href="ttps://skillbox.ru/media/">Skillbox Media</a> без подсказки</p>
193193
<p>
194-
[Skillbox Media](https://skillbox.ru/media/ &amp;quot;Всплывающая
195-
подсказка&amp;quot;) с подсказкой
196-
</p>
197-
<p>[Skillbox Media][1]</p>
198-
<p>[Раздел «Код»][code]</p>
199-
<p>
200-
[1]: https://skillbox.ru/media &amp;quot;Всплывающая подсказка&amp;quot;
201-
[code]: https://skillbox.ru/media/code/
194+
<a href="ttps://skillbox.ru/media/ &amp;quot;Всплывающая подсказка&amp;quot;"
195+
>Skillbox Media</a
196+
>
197+
с подсказкой
202198
</p>
199+
<p><a href="">Skillbox Media</a></p>
200+
<p><a href="">Раздел «Код»</a></p>
201+
<p><a href="">1</a> [code]: https://skillbox.ru/media/code/</p>
203202
<p>
204203
![Изображение](https://upload.wikimedia.org/wikipedia/commons/thumb/4/48/Markdown-mark.svg/1920px-Markdown-mark.svg.png
205204
&amp;quot;Логотип Markdown&amp;quot;)
@@ -256,8 +255,8 @@ <h1 id="967f745ae03431977fb89c965c02c00c">include &amp;lt;stdio.h&amp;gt;</h1>
256255
</tbody>
257256
</table>
258257
<p>
259-
[![An old rock in the desert](./image.png &amp;quot;Shiprock, New Mexico by
260-
Beau
261-
Rogers&amp;quot;)](https://www.flickr.com/photos/beaurogers/31833779864/in/photolist-Qv3rFw-34mt9F-a9Cmfy-5Ha3Zi-9msKdv-o3hgjr-hWpUte-4WMsJ1-KUQ8N-deshUb-vssBD-6CQci6-8AFCiD-zsJWT-nNfsgB-dPDwZJ-bn9JGn-5HtSXY-6CUhAL-a4UTXB-ugPum-KUPSo-fBLNm-6CUmpy-4WMsc9-8a7D3T-83KJev-6CQ2bK-nNusHJ-a78rQH-nw3NvT-7aq2qf-8wwBso-3nNceh-ugSKP-4mh4kh-bbeeqH-a7biME-q3PtTf-brFpgb-cg38zw-bXMZc-nJPELD-f58Lmo-bXMYG-bz8AAi-bxNtNT-bXMYi-bXMY6-bXMYv)
258+
<a href="/image.png &amp;quot;Shiprock, New Mexico by Beau Rogers&amp;quot;"
259+
>![An old rock in the desert</a
260+
>](https://www.flickr.com/photos/beaurogers/31833779864/in/photolist-Qv3rFw-34mt9F-a9Cmfy-5Ha3Zi-9msKdv-o3hgjr-hWpUte-4WMsJ1-KUQ8N-deshUb-vssBD-6CQci6-8AFCiD-zsJWT-nNfsgB-dPDwZJ-bn9JGn-5HtSXY-6CUhAL-a4UTXB-ugPum-KUPSo-fBLNm-6CUmpy-4WMsc9-8a7D3T-83KJev-6CQ2bK-nNusHJ-a78rQH-nw3NvT-7aq2qf-8wwBso-3nNceh-ugSKP-4mh4kh-bbeeqH-a7biME-q3PtTf-brFpgb-cg38zw-bXMZc-nJPELD-f58Lmo-bXMYG-bz8AAi-bxNtNT-bXMYi-bXMY6-bXMYv)
262261
</p>
263262
<p>\\ \` \_ \* \{ \} \[ \] \&amp;lt; \&amp;gt; \( \) # \# \! \|</p>

0 commit comments

Comments
 (0)