Skip to content

Commit

Permalink
give tag enum proper names
Browse files Browse the repository at this point in the history
  • Loading branch information
metagn committed Oct 11, 2024
1 parent 00b7d25 commit 316c35f
Show file tree
Hide file tree
Showing 5 changed files with 69 additions and 65 deletions.
2 changes: 1 addition & 1 deletion margrave.nimble
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
version = "0.4.0"
version = "0.4.1"
author = "metagn"
description = "markdown dialect"
license = "MIT"
Expand Down
5 changes: 4 additions & 1 deletion src/margrave/common.nim
Original file line number Diff line number Diff line change
Expand Up @@ -69,5 +69,8 @@ func toCstring*[T: enum](x: T): cstring =
for i in 1 ..< impl.len:
let e = impl[i]
let z = if e.kind in {nnkIdent, nnkSym}: e else: e[0]
result.add(newTree(nnkOfBranch, z, newAssignment(ident"result", newCall(bindSym"cstring", newLit($e)))))
result.add(newTree(nnkOfBranch, z,
newAssignment(ident"result",
newCall(bindSym"cstring",
newCall(bindSym"$", e)))))
gen(x)
25 changes: 13 additions & 12 deletions src/margrave/element.nim
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,15 @@ import ./common, tables
type
KnownTags* = enum
## Enum of tags used in this library.
noTag,
p, br,
h1, h2, h3, h4, h5, h6,
ul, ol, li, blockquote,
sup, sub, em, strong, pre, code, u, s,
img, input, a,
picture, video, audio, source,
otherTag
tagNone = "",
tagParagraph = "p", tagLineBreak = "br",
tagHeader1 = "h1", tagHeader2 = "h2", tagHeader3 = "h3", tagHeader4 = "h4", tagHeader5 = "h5", tagHeader6 = "h6",
tagUnorderedList = "ul", tagOrderedList = "ol", tagListItem = "li", tagBlockquote = "blockquote",
tagSuperscript = "sup", tagSubscript = "sub", tagItalic = "em", tagBold = "strong",
tagPreformatted = "pre", tagCode = "code", tagUnderline = "u", tagStrikethrough = "s",
tagImage = "img", tagInput = "input", tagLinked = "a",
tagPicture = "picture", tagVideo = "video", tagAudio = "audio", tagSource = "source",
tagOther = "unknownTag"
#text

MargraveElement* {.acyclic.} = ref object
Expand Down Expand Up @@ -38,7 +39,7 @@ type
content*: seq[MargraveElement]
## Inner HTML elements of an HTML element.

const EmptyTags* = {noTag, br, img, input, source, otherTag}
const EmptyTags* = {tagNone, tagLineBreak, tagImage, tagInput, tagSource, tagOther}

when defined(js):
func isEmpty*(tag: KnownTags): bool {.inline.} =
Expand All @@ -63,7 +64,7 @@ func paragraphIfText*(elem: MargraveElement): MargraveElement =
## If `elem` is a text node, turns it into a <p> element.
## Otherwise returns `elem`.
if elem.isText:
MargraveElement(isText: false, tag: p, content: @[elem])
MargraveElement(isText: false, tag: tagParagraph, content: @[elem])
else:
elem

Expand Down Expand Up @@ -135,8 +136,8 @@ func toNativeString*(elem: MargraveElement): NativeString =
var empty = elem.tag.isEmpty
var tag: NativeString
case elem.tag
of noTag: discard # tag stays empty
of otherTag:
of tagNone: discard # tag stays empty
of tagOther:
if elem.hasAttr("tag"):
tag = elem.attr("tag")
empty = elem.hasAttr("emptyTag")
Expand Down
84 changes: 42 additions & 42 deletions src/margrave/parser.nim
Original file line number Diff line number Diff line change
Expand Up @@ -109,7 +109,7 @@ proc parseCodeBlockStr*(parser; options; delimChar: char): tuple[language, code:

proc parseCodeBlock*(parser; options; delimChar: char): MargraveElement {.inline.} =
let str = parseCodeBlockStr(parser, options, delimChar)
result = newElem(pre, @[newStr(str.code)])
result = newElem(tagPreformatted, @[newStr(str.code)])
withOptions(parser, options, not options.codeBlockLanguageHandler.isNil):
if str.language.len != 0:
options.codeBlockLanguageHandler(result, str.language)
Expand Down Expand Up @@ -179,7 +179,7 @@ proc parseDelimed*(parser; options; delim: string, singleLine: SingleLineBool):

proc bracket(image: bool, parser: var MargraveParser): DelimFinishReason =
let elem = parseBracket(parser, options, image, singleLine)
if elem.tag == noTag:
if elem.tag == tagNone:
add(if image: NativeString"![" else: NativeString"[")
add(elem.content)
#result = frFailed
Expand All @@ -196,7 +196,7 @@ proc parseDelimed*(parser; options; delim: string, singleLine: SingleLineBool):
if parser.nextMatch("**"):
let (finishReason, parsedElems) = parseDelimed(parser, options, "**", singleLine)
if finishReason == frDone:
add(newElem(strong, parsedElems))
add(newElem(tagBold, parsedElems))
#inc parser.pos
continue
else:
Expand All @@ -215,7 +215,7 @@ proc parseDelimed*(parser; options; delim: string, singleLine: SingleLineBool):
if parser.nextMatch("__"):
let (finishReason, parsedElems) = parseDelimed(parser, options, "__", singleLine)
if finishReason == frDone:
add(newElem(u, parsedElems))
add(newElem(tagUnderline, parsedElems))
#inc parser.pos
continue
else:
Expand Down Expand Up @@ -254,20 +254,20 @@ proc parseDelimed*(parser; options; delim: string, singleLine: SingleLineBool):
elif not singleLine and (parser.nextMatch("\r\n") or parser.nextMatch("\n")):
dec parser.pos
withOptions(parser, options, options.insertLineBreaks):
add(newElem(br))
add(newElem(tagLineBreak))
do:
add(ch)
of " \r\n", " \n":
dec parser.pos
add(newElem(br))
add(newElem(tagLineBreak))
of "```":
add(parseCodeBlock(parser, options, '`'))
of "~~~":
add(parseCodeBlock(parser, options, '~'))
of "^(": parse(sup, ")")
of "**": parse(strong, "**")
of "__": parse(u, "__")
of "~~": parse(s, "~~")
of "^(": parse(tagSuperscript, ")")
of "**": parse(tagBold, "**")
of "__": parse(tagUnderline, "__")
of "~~": parse(tagStrikethrough, "~~")
of "![":
let reason = bracket(image = true, parser)
if reason in {frFailed, frReachedEnd}:
Expand All @@ -278,13 +278,13 @@ proc parseDelimed*(parser; options; delim: string, singleLine: SingleLineBool):
let reason = bracket(image = false, parser)
if reason in {frFailed, frReachedEnd}:
return (reason, elems)
of '`': parse(code, "`")
of '`': parse(tagCode, "`")
elif parser.noAdjacentWhitespace() and parser.nextMatch('^'):
parse(sup, " ", {frDone, frReachedEnd})
parse(tagSuperscript, " ", {frDone, frReachedEnd})
elif not parser.surroundedWhitespace() and parser.nextMatch('*'):
parse(em, "*")
parse(tagItalic, "*")
elif parser.onlyPrevWhitespace() and parser.nextMatch('_'):
parse(em, "_")
parse(tagItalic, "_")
of '<':
dec parser.pos
var
Expand Down Expand Up @@ -449,7 +449,7 @@ proc parseBracket*(parser; options; image: bool, singleLine: SingleLineBool): Ma
inc parser.pos
let secondPos = parser.pos - 2
if textWorked != frDone:
return newElem(noTag, textElems)
return newElem(tagNone, textElems)
let checkMark =
if not image and textElems.len == 1 and textElems[0].isText and textElems[0].str.len == 1:
case textElems[0].str[0]
Expand All @@ -466,11 +466,11 @@ proc parseBracket*(parser; options; image: bool, singleLine: SingleLineBool): Ma
if link.url.len == 0 and textElems.len == 1 and textElems[0].isText:
link.url = strip(textElems[0].str)
if image:
result = MargraveElement(isText: false, tag: img)
result = MargraveElement(isText: false, tag: tagImage)
if secondPos - firstPos > 0:
result.attrEscaped("alt", parser.str[firstPos..secondPos])
else:
result = MargraveElement(isText: false, tag: a)
result = MargraveElement(isText: false, tag: tagLinked)
result.content = textElems
if link.tip.len != 0:
result.attrEscaped("title", link.tip)
Expand All @@ -487,23 +487,23 @@ proc parseBracket*(parser; options; image: bool, singleLine: SingleLineBool): Ma
if refName.len == 0: refName = parser.str[firstPos..secondPos]
result = MargraveElement(isText: false)
if image:
result.tag = img
result.tag = tagImage
if secondPos - firstPos > 0:
result.attrEscaped("alt", parser.str[firstPos..secondPos])
else:
result.tag = a
result.tag = tagLinked
result.content = textElems
parser.linkReferrers.mgetOrPut(refName, @[]).add(result)
return
else:
dec parser.pos
if image:
# this could be used like a directive tag
result = newElem(noTag, textElems)
result = newElem(tagNone, textElems)
elif checkMark == 0:
result = newElem(if canBeSub: sub else: (dec parser.pos; noTag), textElems)
result = newElem(if canBeSub: tagSubscript else: (dec parser.pos; tagNone), textElems)
else:
result = newElem(input)
result = newElem(tagInput)
result.attr("type", "checkbox")
result.attr("disabled", "")
if checkMark == 2:
Expand All @@ -521,7 +521,7 @@ template parseLine*(parser; options): seq[MargraveElement] =
parseInline(parser, options, singleLine = false)

const
SpecialLineTags* = {ul, ol, blockquote}
SpecialLineTags* = {tagUnorderedList, tagOrderedList, tagBlockquote}
IdStarts* = {'(', '[', '{', ':'}
LegalId* = {'a'..'z', 'A'..'Z', '0'..'9', '-', '_', ':', '.'}
InlineWhitespace* = Whitespace - {'\r', '\n'}
Expand All @@ -546,19 +546,19 @@ proc parseTopLevel*(parser; options): seq[MargraveElement] =
while i < parser.contextStack.len:
let c = parser.contextStack[i]
case c.tag
of ul:
of tagUnorderedList:
if parser.nextMatch({'*', '-', '+'}):
while parser.nextMatch(InlineWhitespace): discard
else: break
of ol:
of tagOrderedList:
let originalPos = parser.pos
while parser.nextMatch(Digits): discard
if parser.nextMatch('.'):
while parser.nextMatch(InlineWhitespace): discard
else:
parser.pos = originalPos
break
of blockquote:
of tagBlockquote:
if parser.nextMatch('>'):
while parser.nextMatch(InlineWhitespace): discard
else: break
Expand Down Expand Up @@ -594,19 +594,19 @@ proc parseTopLevel*(parser; options): seq[MargraveElement] =
newElem(t, els)
if not context.isNil:
case context.tag
of ol, ul:
context.add rawOrNot(li, parseSingleLine(parser, options))
of blockquote:
of tagOrderedList, tagUnorderedList:
context.add rawOrNot(tagListItem, parseSingleLine(parser, options))
of tagBlockquote:
let c = parseSingleLine(parser, options)
if not lastEmptyLine and context.content.len != 0 and
(let last = context[^1]; not last.isText and last.tag == p):
(let last = context[^1]; not last.isText and last.tag == tagParagraph):
addNewline(parser, options, last)
last.add(c)
else:
context.add rawOrNot(p, c)
context.add rawOrNot(tagParagraph, c)
else: discard # unreachable
else:
result.add rawOrNot(p, parseLine(parser, options))
result.add rawOrNot(tagParagraph, parseLine(parser, options))

template addLine(rawLine: static bool = false) =
addLine(parser, options, context, result, lastEmptyLine, rawLine)
Expand All @@ -632,16 +632,16 @@ proc parseTopLevel*(parser; options): seq[MargraveElement] =
else:
addLine()
of '#':
if context.isNil or context.tag in {blockquote, p}:
while not context.isNil and context.tag == p:
if context.isNil or context.tag in {tagBlockquote, tagParagraph}:
while not context.isNil and context.tag == tagParagraph:
let last = parser.contextStack.len - 1
context = parser.contextStack[last]
parser.contextStack.setLen(last)
if last == 0: break
var level = 1
while level < 6 and parser.peekMatch('#', offset = level): inc level
parser.pos += level
let header = newElem(KnownTags(static(h1.int - 1) + level))
let header = newElem(KnownTags(static(tagHeader1.int - 1) + level))
parser.matchNext:
of '|': style header, "text-align:center"
of '<': style header, "text-align:left"
Expand All @@ -654,11 +654,11 @@ proc parseTopLevel*(parser; options): seq[MargraveElement] =
addLine()
of '*', '-', '+':
if parser.nextMatch(InlineWhitespace, offset = 1):
addContext newElem(ul)
addContext newElem(tagUnorderedList)
addLine()
elif parser.nextMatch(IdStarts, offset = 1):
let list = newElem(ul)
var item = newElem(li)
let list = newElem(tagUnorderedList)
var item = newElem(tagListItem)
item.attr("id", parser.parseId(parser.get(-1)))
item.content = parseSingleLine(parser, options)
list.add(item)
Expand All @@ -670,8 +670,8 @@ proc parseTopLevel*(parser; options): seq[MargraveElement] =
inc parser.pos
while parser.nextMatch(Digits): discard
if parser.nextMatch('.'):
let list = newElem(ol)
var item = newElem(li)
let list = newElem(tagOrderedList)
var item = newElem(tagListItem)
if (let ch = parser.get(); parser.nextMatch(IdStarts)):
item.attr("id", parser.parseId(ch))
item.add(parseSingleLine(parser, options))
Expand All @@ -681,7 +681,7 @@ proc parseTopLevel*(parser; options): seq[MargraveElement] =
parser.pos = originalPos
addLine()
of '>':
let quote = newElem(blockquote)
let quote = newElem(tagBlockquote)
inc parser.pos
if (let ch = parser.get(); parser.nextMatch(IdStarts)):
quote.attr("id", parser.parseId(ch))
Expand Down Expand Up @@ -717,7 +717,7 @@ proc parseTopLevel*(parser; options): seq[MargraveElement] =
of '<': align = "text-align:left"
of '>': align = "text-align:right"
else: align = "text-align:center"
let el = newElem(p, parseLine(parser, options))
let el = newElem(tagParagraph, parseLine(parser, options))
style el, align
result.add(el)
elif parser.nextMatch("```"):
Expand Down
18 changes: 9 additions & 9 deletions src/margrave/parser/utils.nim
Original file line number Diff line number Diff line change
Expand Up @@ -32,17 +32,17 @@ proc setLinkDefault*(elem: MargraveElement, link: Link) =
## an audio element; then the `src` attribute will be set to `link`.
## Other tags for `elem` also set the `src` attribute to `link`.
case elem.tag
of a:
of tagLinked:
elem.attrEscaped("href", link.url)
of img:
of tagImage:
let firstUrl = link.url
if (firstUrl.len >= 4 and firstUrl[^4 .. ^1] in [NativeString".mp4", ".m4v", ".mov", ".ogv"]) or
(firstUrl.len >= 5 and firstUrl[^5 .. ^1] == ".webm"):
elem.tag = video
elem.tag = tagVideo
elif (firstUrl.len >= 4 and firstUrl[^4 .. ^1] in [NativeString".mp3", ".oga", ".ogg", ".wav"]) or
(firstUrl.len >= 5 and firstUrl[^5 .. ^1] == ".flac"):
elem.tag = audio
if elem.tag != img:
elem.tag = tagAudio
if elem.tag != tagImage:
elem.attr("controls", "")
var altText: NativeString
if elem.attrs.pop("alt", altText):
Expand All @@ -51,14 +51,14 @@ proc setLinkDefault*(elem: MargraveElement, link: Link) =
elem.attrEscaped("src", link.url)
else:
var sourceAttr: NativeString
if elem.tag == img:
elem.tag = picture
if elem.tag == tagImage:
elem.tag = tagPicture
sourceAttr = "srcset"
else:
sourceAttr = "src"
var i = 0
template addSource(u) =
let srcElem = newElem(source)
let srcElem = newElem(tagSource)
srcElem.attr(sourceAttr, u)
elem.content.insert(srcElem, i)
inc i
Expand All @@ -77,7 +77,7 @@ proc setLink*(parser: MargraveParser, options: static MargraveOptions, elem: Mar

proc addNewline*(parser: MargraveParser, options: static MargraveOptions, elem: MargraveElement | seq[MargraveElement]) =
withOptions(parser, options, options.insertLineBreaks):
elem.add(newElem(br))
elem.add(newElem(tagLineBreak))
do:
elem.add("\n")

Expand Down

0 comments on commit 316c35f

Please sign in to comment.