Page 1 of 1

[Rough] BBCode to HTML Parser

Posted: Mon Nov 28, 2011 12:36 am
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

Re: [Rough] BBCode to HTML Parser

Posted: Mon Nov 28, 2011 3:55 am
by IdeasVacuum
Works well, but why do it in PB?

Re: [Rough] BBCode to HTML Parser

Posted: Mon Nov 28, 2011 8:55 am
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

Re: [Rough] BBCode to HTML Parser

Posted: Mon Nov 28, 2011 11:22 am
by IdeasVacuum
Ah I see - that's a great idea, most people understand how to use BBCode. :mrgreen:

Re: [Rough] BBCode to HTML Parser

Posted: Tue Nov 29, 2011 10:32 am
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)

Re: [Rough] BBCode to HTML Parser

Posted: Tue Nov 29, 2011 12:36 pm
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