1 // Package bbcode implements a bbcode parser and converter 2 package bbcode // import "vimagination.zapto.org/bbcode" 3 4 import ( 5 "io" 6 7 "vimagination.zapto.org/parser" 8 ) 9 10 // Config changes how the syntax of the inteperated bbCode 11 type Config struct { 12 // TagOpen is the character used to open the tags. 13 // In the default configuration this is the open bracket '[' 14 TagOpen rune 15 16 // TagClose is the character used to close the tags. 17 // In the default configuration this is the close bracket ']' 18 TagClose rune 19 20 // ClosingTag is the character used to define a closing tag, as opposed 21 // to an opening tag. 22 // In the default configuration, this is the slash '/' 23 ClosingTag rune 24 25 // AttributeSep is the character used to separate the tag name from the 26 // attribute. 27 // In the default configuration this is the equals sign '=' 28 AttributeSep rune 29 30 // ValidTagName lists the characters that are allowed in the tag names. 31 // Neither of the TagClose or AttributeSep characters should be in this 32 // list. 33 // In the default configuration this is A-Z a-z 0-9 and the asterix 34 ValidTagName string 35 } 36 37 var defaultConfig = Config{ 38 TagOpen: '[', 39 TagClose: ']', 40 ClosingTag: '/', 41 AttributeSep: '=', 42 ValidTagName: "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789*", 43 } 44 45 // BBCode is a fully configured parser 46 type BBCode struct { 47 tks tokeniser 48 text Handler 49 tags []Handler 50 } 51 52 // NewWithConfig creates a bbCode parser with a custom bbCode configuration. 53 // The tags are a list of Handlers that will be used to process the tag tokens 54 // that are generated by the parser. 55 // The first Handler with an empty string for a name with be used to process 56 // the text. By default, this is the HTMLText handler. 57 func NewWithConfig(c Config, tags ...Handler) *BBCode { 58 var text Handler = HTMLText 59 for _, tag := range tags { 60 if tag.Name() == "" { 61 text = tag 62 break 63 } 64 } 65 return &BBCode{ 66 tks: getTokeniser(c), 67 text: text, 68 tags: tags, 69 } 70 } 71 72 // New create a new bbCode parser with the default configuration. 73 // See NewWithConfig for more information 74 func New(tags ...Handler) *BBCode { 75 return NewWithConfig(defaultConfig, tags...) 76 } 77 78 // Convert parses the byte slice and writes the output to the writer. 79 // Any error will be from the writing process and not from the parser 80 func (b *BBCode) Convert(w io.Writer, input []byte) error { 81 return b.convert(w, parser.NewByteTokeniser(input)) 82 } 83 84 // ConvertString functions like Convert, but takes a string 85 func (b *BBCode) ConvertString(w io.Writer, input string) error { 86 return b.convert(w, parser.NewStringTokeniser(input)) 87 } 88 89 // ConvertReader functions like Convert, but takes a io.Reader 90 func (b *BBCode) ConvertReader(w io.Writer, input io.Reader) error { 91 return b.convert(w, parser.NewReaderTokeniser(input)) 92 } 93 94 func (b *BBCode) convert(w io.Writer, t parser.Tokeniser) error { 95 p := Processor{ 96 w: w, 97 p: b.tks.getParser(t), 98 bbCode: b, 99 } 100 p.Process("") 101 return p.err 102 } 103