[Rough] BBCode to HTML Parser

Share your advanced PureBasic knowledge/code with the community.
Env
Enthusiast
Enthusiast
Posts: 151
Joined: Tue Apr 27, 2010 3:20 pm
Location: Wales, United Kingdom

[Rough] BBCode to HTML Parser

Post by Env »

Hello All,

Came up with a bit of a grubby (not perfect) way of translating a document with BBCode into a HTML document.

Code: Select all

EnableExplicit

Structure __BBCodeToHTML_TagData
  *m_pHandler
EndStructure

Structure __BBCodeToHTML_GlobalData
  m_backColor.l
  m_foreColor.l
  m_font.s
  m_fontSize.l
  m_replacement.s
  m_currentTag.s
  Map m_tags.__BBCodeToHTML_TagData()
  Map m_args.s()
EndStructure

Global __BBCodeToHTML_Global.__BBCodeToHTML_GlobalData

With __BBCodeToHTML_Global
  \m_font = "arial"
  \m_fontSize = 2
  \m_foreColor = #Black
  \m_backColor = #White
EndWith

Procedure __BBCodeToHTML_DefaultHandler()
  With __BBCodeToHTML_Global    
    Select \m_currentTag        
      Case "b" ; Bold Text
        \m_replacement = "<b>"
      Case "/b"
        \m_replacement = "</b>"      
      Case "i" ; Italic Text
        \m_replacement = "<i>"
      Case "/i"
        \m_replacement = "</i>"        
      Case "u" ; Underlined Text
        \m_replacement = "<u>"
      Case "/u"
        \m_replacement = "</u>"        
      Case "s" ; StrikeThrough Text
        \m_replacement = "<s>"
      Case "/s"
        \m_replacement = "</s>"         
      Case "size" ; Text Size
        \m_replacement = "<span style=" + Chr(34) + "font-size:" + \m_args("size") + "px" + Chr(34) + ">"
      Case "/size"
        \m_replacement = "</span>"         
      Case "url" ; Link
        \m_replacement = "<a href=" + Chr(34) + \m_args("url") + Chr(34) + ">"
      Case "/url"
        \m_replacement = "</a>"
      Case "color" ; Text Colour
        \m_replacement = "<span style=" + Chr(34) + "color:" + \m_args("color") + ";" + Chr(34) + ">"
      Case "/color"
        \m_replacement = "</span>"
      Case "quote" ; Quotation
        \m_replacement = "<blockquote><p>"
      Case "/quote"
        \m_replacement = "</p></blockquote>"
      Case "code" ; Code
        \m_replacement = "<pre>"
      Case "/code"
        \m_replacement = "</pre>"
        Case "left" ; Align Left
        \m_replacement = "<div align=" + Chr(34) + "left" + Chr(34) + ">"
      Case "/left"
        \m_replacement = "</div>"
        Case "center" ; Align Center
        \m_replacement = "<div align=" + Chr(34) + "center" + Chr(34) + ">"
      Case "/center"
        \m_replacement = "</div>"
      Case "right" ; Align Right
        \m_replacement = "<div align=" + Chr(34) + "right" + Chr(34) + ">"
      Case "/right"
        \m_replacement = "</div>"
      Case "ol" ; Ordered List
        \m_replacement = "<ol>"
      Case "/ol"
        \m_replacement = "</ol>"
      Case "ul", "list" ; Unordered List
        \m_replacement = "<ul>"
      Case "/ul", "/list"
        \m_replacement = "</ul>"  
       Case "li", "*" ; List Item
        \m_replacement = "<li>"
      Case "/li", "/*"
        \m_replacement = "</li>"
      Case "hr" ; Horizontal Line
        \m_replacement = "<hr>"
    EndSelect
  EndWith
EndProcedure

Procedure.l __BBCodeToHTML_FindNextDelimiter(Line$, StartPosition)
  Protected cIx.l
  For cIx = StartPosition To Len(Line$)
    If FindString(" ]=", Mid(Line$, cIx, 1))
      ProcedureReturn cIx
    EndIf
  Next
  ProcedureReturn Len(Line$)
EndProcedure

Procedure.l __BBCodeToHTML_FindNextClosure(Line$, StartPosition)
  Protected cIx.l
  For cIx = StartPosition To Len(Line$)
    If FindString("]", Mid(Line$, cIx, 1))
      ProcedureReturn cIx
    EndIf
  Next
  ProcedureReturn Len(Line$)
EndProcedure

Procedure.s __BBCodeToHTML_ParseLine(Line$)
  Protected cIx.l, cArgIx.l, cChar.s, nDelimiter.l, nClosure.l, cTag.s, cArgList.s, cArgName.s, cArgVal.s, argCnt.l, output.s
  For cIx = 1 To Len(Line$)
    cChar = Mid(Line$, cIx, 1)
    If cChar = "["
      nDelimiter = __BBCodeToHTML_FindNextDelimiter(Line$, cIx)
      nClosure = __BBCodeToHTML_FindNextClosure(Line$, cIx)
      cTag = Mid(Line$, cIx, nDelimiter - cIx)
      cTag = Right(cTag, Len(cTag) - 1)
      If FindMapElement(__BBCodeToHTML_Global\m_tags(), LCase(cTag))
        If nDelimiter <> nClosure
          cArgList = Mid(Line$, cIx + Len(cTag) + 1, nClosure - (cIx + Len(cTag) + 1))
          cArgList = Trim(cArgList)
          argCnt = CountString(cArgList, " ") + 1
          For cArgIx = 1 To argCnt
            cArgName = StringField(StringField(cArgList, cArgIx, " "), 1, "=")
            cArgVal = StringField(StringField(cArgList, cArgIx, " "), 2, "=")
            If cArgName = ""
              cArgName = cTag
            EndIf
            __BBCodeToHTML_Global\m_args(LCase(cArgName)) = cArgVal
          Next
        EndIf
        __BBCodeToHTML_Global\m_currentTag = LCase(cTag)
        __BBCodeToHTML_Global\m_replacement = ""
        If __BBCodeToHTML_Global\m_tags(LCase(cTag))\m_pHandler <> #Null
          CallFunctionFast(__BBCodeToHTML_Global\m_tags(LCase(cTag))\m_pHandler)
        EndIf
        cChar = ""
        cIx = nClosure
        output = output + __BBCodeToHTML_Global\m_replacement
      EndIf
    EndIf
    If cChar <> ""
      output = output + cChar
    EndIf
  Next    
  ProcedureReturn output
EndProcedure

Procedure BBCodeToHTML_SetTagHandler(Tag.s, *Function)
  If *Function
    __BBCodeToHTML_Global\m_tags(LCase(Tag))\m_pHandler = *Function
    __BBCodeToHTML_Global\m_tags("/" + LCase(Tag))\m_pHandler = *Function
  Else
    DeleteMapElement(__BBCodeToHTML_Global\m_tags(), LCase(Tag))
  EndIf
EndProcedure

BBCodeToHTML_SetTagHandler("b", @__BBCodeToHTML_DefaultHandler())
BBCodeToHTML_SetTagHandler("i", @__BBCodeToHTML_DefaultHandler())
BBCodeToHTML_SetTagHandler("u", @__BBCodeToHTML_DefaultHandler())
BBCodeToHTML_SetTagHandler("s", @__BBCodeToHTML_DefaultHandler())
BBCodeToHTML_SetTagHandler("url", @__BBCodeToHTML_DefaultHandler())
BBCodeToHTML_SetTagHandler("quote", @__BBCodeToHTML_DefaultHandler())
BBCodeToHTML_SetTagHandler("code", @__BBCodeToHTML_DefaultHandler())
BBCodeToHTML_SetTagHandler("size", @__BBCodeToHTML_DefaultHandler())
BBCodeToHTML_SetTagHandler("color", @__BBCodeToHTML_DefaultHandler())
BBCodeToHTML_SetTagHandler("left", @__BBCodeToHTML_DefaultHandler())
BBCodeToHTML_SetTagHandler("center", @__BBCodeToHTML_DefaultHandler())
BBCodeToHTML_SetTagHandler("right", @__BBCodeToHTML_DefaultHandler())
BBCodeToHTML_SetTagHandler("ol", @__BBCodeToHTML_DefaultHandler())
BBCodeToHTML_SetTagHandler("ul", @__BBCodeToHTML_DefaultHandler())
BBCodeToHTML_SetTagHandler("li", @__BBCodeToHTML_DefaultHandler())
BBCodeToHTML_SetTagHandler("list", @__BBCodeToHTML_DefaultHandler())
BBCodeToHTML_SetTagHandler("*", @__BBCodeToHTML_DefaultHandler())
BBCodeToHTML_SetTagHandler("hr", @__BBCodeToHTML_DefaultHandler())

Procedure BBCodeToHTML_SetBackgroundColour(Colour = #White)
  __BBCodeToHTML_Global\m_backColor = Colour
EndProcedure

Procedure BBCodeToHTML_SetTextColour(Colour = #Black)
  __BBCodeToHTML_Global\m_foreColor = Colour
EndProcedure

Procedure BBCodeToHTML_SetTextFont(Font$ = "Arial")
  __BBCodeToHTML_Global\m_font = Font$
EndProcedure

Procedure BBCodeToHTML_SetTextSize(Size = 4)
  __BBCodeToHTML_Global\m_fontSize = Size
EndProcedure

Procedure.s BBCodeToHTML(Document$)
  Protected output.s
  output = "<html><body bgcolor=" + Chr(34) + "rgb(" + Str(Red(__BBCodeToHTML_Global\m_backColor)) + ","+ Str(Green(__BBCodeToHTML_Global\m_backColor)) + "," + Str(Blue(__BBCodeToHTML_Global\m_backColor)) + ")" + Chr(34) + ">"
  output = output + "<basefont color=" + Chr(34) + "rgb(" + Str(Red(__BBCodeToHTML_Global\m_foreColor)) + ","+ Str(Green(__BBCodeToHTML_Global\m_foreColor)) + "," + Str(Blue(__BBCodeToHTML_Global\m_foreColor)) + ")" + Chr(34) + " face=" + Chr(34) +__BBCodeToHTML_Global\m_font + Chr(34) + " size=" + Chr(34) + Str(__BBCodeToHTML_Global\m_fontSize) + Chr(34) + ">"
  output = output + __BBCodeToHTML_ParseLine(Document$)
  output = output + "</body></html>"
  ProcedureReturn output
EndProcedure

; -------------------------------------------------------------------------------------
; - DEMONSTRATION CODE - DEMONSTRATION CODE - DEMONSTRATION CODE - DEMONSTRATION CODE -
; -------------------------------------------------------------------------------------

Define Document.s = "[url=http://www.google.com][size=20]This is a link to Google[/size][/url] and [color=red]This is Coloured Text![/color]" + #LF$
Document + "[quote]Some Quoted Text![/quote]" + #LF$
Document + "[code]Some Formatted Code
" + #LF$
Document + "[right]Bold Text aligned to the Right[/right]" + #LF$
Document + "[center]Italic Text aligned to the Center[/center]" + #LF$
Document + "[left]Underlined Text aligned to the Left[/left]" + #LF$
Document + "[hr]" + #LF$
Document + "
  • Unordered Item 1
  • [li]Unordered Item 2[/li]
" + #LF$
Document + "[ol][*]Ordered Item 1[/*][li]Ordered Item 2[/li][/ol]" + #LF$

; - Configure Apperance -
BBCodeToHTML_SetBackgroundColour(RGB(0, 0, 80))
BBCodeToHTML_SetTextColour(#White)
BBCodeToHTML_SetTextFont("arial")
BBCodeToHTML_SetTextSize(3)

OpenWindow(0, #PB_Ignore, #PB_Ignore, 800, 600, "Test", #PB_Window_ScreenCentered | #PB_Window_SystemMenu)
WebGadget(0, 0, 0, 800, 600, "")
SetGadgetItemText(0, #PB_Web_HtmlCode , BBCodeToHTML(Document))

Repeat
Select WindowEvent()
Case #PB_Event_CloseWindow
End
EndSelect
ForEver[/code]

I am looking to improve it, and make it more efficient, as well as able to handle BBCode perfectly, and would love some input from the community.


Thanks :D
Last edited by Env on Mon Nov 28, 2011 9:24 am, edited 2 times in total.
Thanks!
IdeasVacuum
Always Here
Always Here
Posts: 6426
Joined: Fri Oct 23, 2009 2:33 am
Location: Wales, UK
Contact:

Re: [Rough] BBCode to HTML Parser

Post by IdeasVacuum »

Works well, but why do it in PB?
IdeasVacuum
If it sounds simple, you have not grasped the complexity.
Env
Enthusiast
Enthusiast
Posts: 151
Joined: Tue Apr 27, 2010 3:20 pm
Location: Wales, United Kingdom

Re: [Rough] BBCode to HTML Parser

Post by Env »

Hey IdeasVacuum,

The initial idea for the little utility was to aid me in the rapid creation of documentation files within something I am currently working on...

So you create a document in a text editor using bbcode, and then it will translate it into html with the added ability to customise how elements are written.

Plain text is ok, but I wanted something with a bit more freedom, and I just liked the easy-to-use way BBCode handles this... and it's well known by many lol.

Update
Support for Horizontal Lines, and Lists (Ordered & Unordered) added.


Thanks :D
Thanks!
IdeasVacuum
Always Here
Always Here
Posts: 6426
Joined: Fri Oct 23, 2009 2:33 am
Location: Wales, UK
Contact:

Re: [Rough] BBCode to HTML Parser

Post by IdeasVacuum »

Ah I see - that's a great idea, most people understand how to use BBCode. :mrgreen:
IdeasVacuum
If it sounds simple, you have not grasped the complexity.
User avatar
Kwai chang caine
Always Here
Always Here
Posts: 5494
Joined: Sun Nov 05, 2006 11:42 pm
Location: Lyon - France

Re: [Rough] BBCode to HTML Parser

Post by Kwai chang caine »

yeees !!! great code and idea 8)
I love all the code who convert a language in another :wink:

Thanks a lot for sharing 8)
ImageThe happiness is a road...
Not a destination
Env
Enthusiast
Enthusiast
Posts: 151
Joined: Tue Apr 27, 2010 3:20 pm
Location: Wales, United Kingdom

Re: [Rough] BBCode to HTML Parser

Post by Env »

Thanks guys :)

Still a lot of stuff to add in to this... I.e. Making the text body of the document 'html friendly' by further parsing it for characters that need to be substituted for HTML elements. (i.e. '<' would become '<' and so on).

Might even piece together a little GUI editor too.. Depends on how much free time I have in the next coming days lol.



All the best :D
Thanks!
Post Reply