Skip to content

Instantly share code, notes, and snippets.

@ZoomTen
Created December 29, 2024 15:59
Show Gist options
  • Save ZoomTen/b45e387733cc5f1df05bcc148c85ac4a to your computer and use it in GitHub Desktop.
Save ZoomTen/b45e387733cc5f1df05bcc148c85ac4a to your computer and use it in GitHub Desktop.
##[
An extremely basic BBcode parser
Not quite ready for the works.
Will turn into a package later
Supports no parameters yet.
2 blank lines = 1 manual line break
3 blank lines = 2 manual line break
and so on
]##
from strutils import nil
proc bbCode2Html*(input: string): string =
let text = strutils.strip(input)
var rendered: string
var inBracket = false
var isEndCommand = false
var commandBuffer = ""
var bracketStack: seq[string] = @[]
var numCharactersEncountered = 0
var blankLinesEncountered = 0
for i in text:
if i == '\n':
inc(blankLinesEncountered)
if blankLinesEncountered > 1:
rendered.add "<br>"
else:
blankLinesEncountered = 0
case i
of '[':
# lookahead one character
let lookaheadIndex = numCharactersEncountered + 1
if lookaheadIndex > (len(text) - 1):
# there is no other character!
rendered.add '['
else:
if text[lookaheadIndex] == '[':
# this is an escaped [
rendered.add '['
elif text[lookaheadIndex] in ({'a' .. 'z'}):
# we have a command
inBracket = true
elif text[lookaheadIndex] == '/':
# we have an ending command
inBracket = true
isEndCommand = true
of ']':
if inBracket:
if isEndCommand:
isEndCommand = false
let commandTerm = bracketStack.pop()
assert(commandTerm == commandBuffer)
rendered.add(
case commandTerm
of "center": "</div>"
of "big": "</span>"
of "ul": "</ul>"
of "li": "</li>"
of "b": "</b>"
of "i": "</i>"
of "u": "</u>"
else: ""
)
else:
bracketStack.add commandBuffer
rendered.add(
case commandBuffer
of "center": "<div class=\"bbcode-center\">"
of "big": "<span class=\"bbcode-big\">"
of "ul": "<ul class=\"proper-list\">"
of "li": "<li>"
of "b": "<b>"
of "i": "<i>"
of "u": "<u>"
else: ""
)
commandBuffer.setLen(0)
inBracket = false
else:
# lookahead one character
let lookaheadIndex = numCharactersEncountered + 1
if lookaheadIndex > (len(text) - 1):
# there is no other character!
if inBracket:
# clean up
inBracket = false
else:
rendered.add ']'
else:
if text[lookaheadIndex] == ']':
# this is an escaped ]
rendered.add ']'
of '<':
rendered.add "&lt;"
of '>':
rendered.add "&gt;"
of '&':
rendered.add "&amp;"
else:
if inBracket:
if i in {'a' .. 'z'}:
commandBuffer.add i
else:
rendered.add i
inc(numCharactersEncountered)
assert(not inBracket)
assert(not isEndCommand)
assert(len(bracketStack) < 1)
assert(numCharactersEncountered == len(text))
return rendered
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment