feat: tags and footnotes
This commit is contained in:
parent
ead9839afe
commit
1b49a94d22
|
@ -3,7 +3,7 @@
|
||||||
Turn IncDown into HTML.
|
Turn IncDown into HTML.
|
||||||
First attempt at a parser, written in [Fennel](https://fennel-lang.org/)
|
First attempt at a parser, written in [Fennel](https://fennel-lang.org/)
|
||||||
|
|
||||||
Input -> Block Lexxing -> Inline Lexer -> Rendered?
|
Input -> Block Lexer -> Inline Lexer -> Renderer
|
||||||
|
|
||||||
I think that's how this will work
|
I think that's how this will work
|
||||||
|
|
||||||
|
@ -15,7 +15,7 @@ The other thing I need to work out is how to handle metadata and sections, and w
|
||||||
|
|
||||||
::
|
::
|
||||||
|
|
||||||
- Code fencse are now working, but it's ugly as fuck. I have previously been using the older markdown starnard that uses `{{{` to open a fence and `}}}` to close one. This meant I needed a seperate check to parse the end of the block, but all other blocks work by applying the same regex (which should match *every* line). Code fences, (even if using ``` instead of {{{) would not match every block, but instead begins a "mode", which even if the pattern doesn't match, we add it to the current block.
|
- Code fences are now working, but it's ugly as fuck. I have previously been using the older markdown starnard that uses `{{{` to open a fence and `}}}` to close one. This meant I needed a seperate check to parse the end of the block, but all other blocks work by applying the same regex (which should match *every* line). Code fences, (even if using ``` instead of {{{) would not match every block, but instead begins a "mode", which even if the pattern doesn't match, we add it to the current block.
|
||||||
|
|
||||||
::
|
::
|
||||||
|
|
||||||
|
@ -56,7 +56,7 @@ Block parser breaks the text up into blocks:
|
||||||
|
|
||||||
= Inline =
|
= Inline =
|
||||||
- Decorations
|
- Decorations
|
||||||
- Links
|
- Links (Internal & External)
|
||||||
- Images? Maybe images can't be inlined?
|
- Images? Maybe images can't be inlined?
|
||||||
- Footnotes
|
- Footnotes
|
||||||
|
|
||||||
|
|
64
main.fnl
64
main.fnl
|
@ -8,9 +8,14 @@
|
||||||
{:name "Image"
|
{:name "Image"
|
||||||
:sp-chars ["!["]
|
:sp-chars ["!["]
|
||||||
:regex "!%[.-%]%(.-%)\n"}
|
:regex "!%[.-%]%(.-%)\n"}
|
||||||
|
{:name "Tag"
|
||||||
|
:sp-chars [":"]
|
||||||
|
:end-also true
|
||||||
|
:regex ":.-:\n"}
|
||||||
{:name "Quote"
|
{:name "Quote"
|
||||||
:any-space true
|
:any-space true
|
||||||
:sp-chars [">"]
|
:sp-chars [">"]
|
||||||
|
:continue-until-no-match true
|
||||||
:regex "%s*>.-\n"}
|
:regex "%s*>.-\n"}
|
||||||
{:name "Metadata"
|
{:name "Metadata"
|
||||||
:sp-chars ["%"]
|
:sp-chars ["%"]
|
||||||
|
@ -29,10 +34,15 @@
|
||||||
:any-space true
|
:any-space true
|
||||||
:continue-until-no-match true
|
:continue-until-no-match true
|
||||||
:regex "%s*[%-%#].-\n"}
|
:regex "%s*[%-%#].-\n"}
|
||||||
|
{:name "Footnote"
|
||||||
|
:sp-chars ["::\n"]
|
||||||
|
:regex "%s*::%s-\n"
|
||||||
|
:capture-mode true
|
||||||
|
:mode-regex "%s*::%s-\n"}
|
||||||
{:name "Paragraph"
|
{:name "Paragraph"
|
||||||
:regex ".-\n"}])
|
:regex ".-\n"}])
|
||||||
|
|
||||||
(fn parse-blocks [{: contents : grammar}]
|
(fn block-lexer [{: contents : grammar}]
|
||||||
(var current 1)
|
(var current 1)
|
||||||
(var blocks [])
|
(var blocks [])
|
||||||
(var current-block-type nil)
|
(var current-block-type nil)
|
||||||
|
@ -51,9 +61,9 @@
|
||||||
(tostring (. g :mode-regex)))))
|
(tostring (. g :mode-regex)))))
|
||||||
(let [m (if (not capture-mode)
|
(let [m (if (not capture-mode)
|
||||||
(string.match current-str (. g :regex)) ; We're not in previous capture mode
|
(string.match current-str (. g :regex)) ; We're not in previous capture mode
|
||||||
(if (= (. g :name) current-block-type)
|
(if (= (. g :name) current-block-type) ; And the regex we're checking is the one we want
|
||||||
(string.match current-str (. g :mode-regex))
|
(string.match current-str (. g :mode-regex)) ; Use the mode specific regex
|
||||||
nil))] ; Use the mode specific regex
|
nil))] ; Or don't check
|
||||||
(print (.. "M: " (tostring m)))
|
(print (.. "M: " (tostring m)))
|
||||||
(if (not (= nil m)) ; This is a match or move on
|
(if (not (= nil m)) ; This is a match or move on
|
||||||
(do
|
(do
|
||||||
|
@ -79,7 +89,7 @@
|
||||||
(set capture-mode (. g :capture-mode))
|
(set capture-mode (. g :capture-mode))
|
||||||
(set current-block (.. current-block current-str "\n"))
|
(set current-block (.. current-block current-str "\n"))
|
||||||
(print (.. "Set current-block: " current-block)))
|
(print (.. "Set current-block: " current-block)))
|
||||||
(do ; Else we start a new block
|
(do ; Else we start a new block, and insert our accumulation
|
||||||
(table.insert blocks {:type current-block-type
|
(table.insert blocks {:type current-block-type
|
||||||
:block current-block})
|
:block current-block})
|
||||||
(print (.. "Inserted into table: " current-block))
|
(print (.. "Inserted into table: " current-block))
|
||||||
|
@ -89,38 +99,54 @@
|
||||||
(print (.. "New Capture-mode: " (tostring (. g :capture-mode))))
|
(print (.. "New Capture-mode: " (tostring (. g :capture-mode))))
|
||||||
(set current-block-type (. g :name))))
|
(set current-block-type (. g :name))))
|
||||||
(set current (+ 1 start)))
|
(set current (+ 1 start)))
|
||||||
(if (and
|
(if (and ; We didn't match, BUT
|
||||||
capture-mode ; Or we're in capture mode *and didn't match*
|
capture-mode ; Or we're in capture mode
|
||||||
(= (. g :name) current-block-type)) ; And are testing the right regex
|
(= (. g :name) current-block-type)) ; And are testing the right regex (should be implicitly true if we reached here)
|
||||||
(do
|
(do
|
||||||
(print (.. "Didnt match capture-mode regex, appending anyway"))
|
(print (.. "Didnt match capture-mode regex, appending anyway"))
|
||||||
(set current-block (.. current-block current-str "\n"))
|
(set current-block (.. current-block current-str "\n"))
|
||||||
(print (.. "New current-block: " current-block))
|
(print (.. "New current-block: " current-block))
|
||||||
(set matched true)
|
(set matched true) ; We don't need to check the others
|
||||||
(set current (+ 1 start)))))))))
|
(set current (+ 1 start)))))))))
|
||||||
|
|
||||||
(print "End of file reached, unloading current")
|
(print "End of file reached, unloading current")
|
||||||
(table.insert blocks {:type current-block-type
|
(table.insert blocks {:type current-block-type
|
||||||
:block current-block})
|
:block current-block})
|
||||||
blocks)
|
blocks)
|
||||||
|
|
||||||
; Each \n point
|
; Each \n point
|
||||||
; Read contents from current to next
|
; Read contents from current to next \n
|
||||||
; If it matches any of the block structures
|
; If it matches the regex
|
||||||
; Add to that blocks current
|
; Either it's the same pattern as the last one (or the last one was nil), so we continue adding to the block-accumulator
|
||||||
; If the block is complete, add it to the blocks list
|
; Or it's a different pattern, which means the current block is complete add it to the blocks list, and start a new accumulator filled with our current-str
|
||||||
; If not, continue with block descent
|
; If not, continue with block descent
|
||||||
|
|
||||||
; (let [start (string.find "This is a paragraph.\n- This\n- List\n- Should\n- Be One\n" "\n" 1)]
|
(fn inline-lexer [blocks grammar]
|
||||||
; (print start))
|
(var lexed [])
|
||||||
|
(each [_ block (ipairs blocks)]
|
||||||
|
(match (. block :type)
|
||||||
|
"Paragraph"
|
||||||
|
(do)
|
||||||
|
"Footnote"
|
||||||
|
(do)
|
||||||
|
"List"
|
||||||
|
(do)
|
||||||
|
"Header"
|
||||||
|
(do)
|
||||||
|
"Image"
|
||||||
|
(do)
|
||||||
|
"Metadata"
|
||||||
|
(do)
|
||||||
|
"Code"
|
||||||
|
(do))))
|
||||||
|
|
||||||
|
; This string has weird behaviour in nvim conjure repl
|
||||||
; (string.match "{{{python\n return arg + 1\n}}}\n" "{{{.-\n.-}}}\n")
|
; (string.match "{{{python\n return arg + 1\n}}}\n" "{{{.-\n.-}}}\n")
|
||||||
|
|
||||||
; (= [{:type "Paragraph"
|
; (= [{:type "Paragraph"
|
||||||
; :block "This is a paragraph."
|
; :block "This is a paragraph."
|
||||||
; {:type "List"
|
; {:type "List"
|
||||||
; :block "- This\n- List\n- Should\n- Be One"}
|
; :block "- This\n- List\n- Should\n- Be One"}
|
||||||
(parse-blocks
|
|
||||||
{:contents "= Big Test File =\n%title Some Title\nThis is a paragraph.\n- This\n- List\n- Should\n- Be One\n-----\n= A new Section Title =\n![Has an Image](file:///link-to-image.png)\n> With some quoted matieral\n>Across multiple lines\n > and different indents\n\n{{{python \n def file(arg, other):\n rturn rg + other\n}}}\n\nMore Paragraphs\n"
|
|
||||||
:grammar block-grammar})
|
|
||||||
|
|
||||||
|
(block-lexer
|
||||||
|
{:contents "= Big Test File =\n%title Some Title\n:note:\nThis is a paragraph.\n- This\n- List\n- Should\n- Be One\n-----\n= A new Section Title =\n![Has an Image](file:///link-to-image.png)\n> With some quoted matieral\n>Across multiple lines\n > and different indents\n\n{{{python \n def file(arg, other):\n rturn rg + other\n}}}\n\nMore Paragraphs\n-----\n:: \n\n- This is the first note\n-This is the second\n"
|
||||||
|
:grammar block-grammar})
|
||||||
|
|
Loading…
Reference in a new issue