191 lines
4.3 KiB
Go
191 lines
4.3 KiB
Go
package wikitext_parser
|
|
|
|
import (
|
|
"fmt"
|
|
"strings"
|
|
)
|
|
|
|
type Template struct {
|
|
Name string
|
|
IsLink bool
|
|
Parameters map[string][]interface{}
|
|
UnkeyedIndex int
|
|
}
|
|
|
|
func NewTemplate(name string, isLink bool) *Template {
|
|
return &Template{
|
|
Name: name,
|
|
IsLink: isLink,
|
|
Parameters: make(map[string][]interface{}),
|
|
}
|
|
}
|
|
|
|
func (t *Template) AddParameterUnkeyed(value interface{}) {
|
|
t.AddParameter(fmt.Sprintf("%d", t.UnkeyedIndex), value)
|
|
}
|
|
|
|
func (t *Template) AddParameter(key string, value interface{}) {
|
|
if _, ok := t.Parameters[key]; !ok {
|
|
t.Parameters[key] = make([]interface{}, 0, 1)
|
|
}
|
|
t.Parameters[key] = append(t.Parameters[key], value)
|
|
}
|
|
|
|
func ParseTemplate(text string, index int, depth int, startCharacter byte) (i int, template *Template) {
|
|
|
|
var c byte
|
|
lastToken := index
|
|
|
|
var key string
|
|
|
|
addValue := func() int {
|
|
if lastToken < len(text) && i-lastToken > 0 {
|
|
t := strings.TrimSpace(text[lastToken:i])
|
|
if len(t) > 0 {
|
|
if template == nil {
|
|
template = NewTemplate(t, startCharacter == '[')
|
|
} else {
|
|
if key == "" {
|
|
template.AddParameterUnkeyed(text[lastToken:i])
|
|
} else {
|
|
template.AddParameter(key, text[lastToken:i])
|
|
}
|
|
}
|
|
}
|
|
|
|
return len(t)
|
|
}
|
|
|
|
return 0
|
|
}
|
|
addKey := func() {
|
|
if lastToken < len(text) && i-lastToken > 0 {
|
|
t := strings.TrimSpace(text[lastToken:i])
|
|
if len(t) > 0 {
|
|
key = t
|
|
}
|
|
}
|
|
}
|
|
|
|
afterNewLine := false
|
|
|
|
for i = index; i < len(text); i++ {
|
|
c = text[i]
|
|
|
|
if startCharacter == '{' && c == '}' && i < len(text)-1 && text[i+1] == '}' { //end of template
|
|
addValue()
|
|
i += 2
|
|
break
|
|
} else if startCharacter == '[' && c == ']' && i < len(text)-1 && text[i+1] == ']' { //end of link
|
|
addValue()
|
|
i += 2
|
|
break
|
|
//template or light might have parameters
|
|
} else if (c == '{' && i < len(text)-1 && text[i+1] == '{') || (c == '[' && i < len(text)-1 && text[i+1] == '[') {
|
|
addValue()
|
|
var tpl *Template
|
|
var scanIndex int
|
|
scanIndex, tpl = ParseTemplate(text, i+2, depth+1, c)
|
|
if tpl != nil {
|
|
if key == "" {
|
|
template.AddParameterUnkeyed(tpl)
|
|
} else {
|
|
template.AddParameter(key, tpl)
|
|
}
|
|
}
|
|
lastToken = scanIndex
|
|
i = scanIndex - 1
|
|
} else if (c == '{' && i < len(text)-1 && text[i+1] != '{' && text[i+1] != '[') || (c == '[' && i < len(text)-1 && text[i+1] != '[' && text[i+1] != '{') {
|
|
addValue()
|
|
var link *Link
|
|
var scanIndex int
|
|
scanIndex, link = ParseLink(text, i+1, depth+1, c)
|
|
if link != nil && template != nil {
|
|
if key == "" {
|
|
template.AddParameterUnkeyed(link)
|
|
} else {
|
|
template.AddParameter(key, link)
|
|
}
|
|
}
|
|
lastToken = scanIndex
|
|
i = scanIndex - 1
|
|
} else if c == '<' { //html trigger
|
|
addValue()
|
|
var html *HTML
|
|
var scanIndex int
|
|
scanIndex, html = ParseHTML(text, i, depth+1)
|
|
if html != nil && template != nil {
|
|
if key == "" {
|
|
template.AddParameterUnkeyed(html)
|
|
} else {
|
|
template.AddParameter(key, html)
|
|
}
|
|
}
|
|
lastToken = scanIndex
|
|
i = scanIndex - 1
|
|
} else if c == '|' {
|
|
hasTemplate := template != nil
|
|
addValue()
|
|
lastToken = i + 1
|
|
if hasTemplate {
|
|
template.UnkeyedIndex++
|
|
}
|
|
key = ""
|
|
} else if c == '\n' {
|
|
addValue()
|
|
lastToken = i + 1
|
|
afterNewLine = true
|
|
|
|
if template != nil {
|
|
if key == "" {
|
|
template.AddParameterUnkeyed(NewLineToken{})
|
|
} else {
|
|
template.AddParameter(key, NewLineToken{})
|
|
}
|
|
}
|
|
} else if afterNewLine && (c == '*' || c == '#') {
|
|
addValue()
|
|
var list *UnorderedList
|
|
var scanIndex int
|
|
scanIndex, list = ParseUnorderedList(text, i, depth+1, 1, c)
|
|
if list != nil {
|
|
if key == "" {
|
|
template.AddParameterUnkeyed(list)
|
|
} else {
|
|
template.AddParameter(key, list)
|
|
}
|
|
}
|
|
lastToken = scanIndex
|
|
i = scanIndex - 1
|
|
} else if afterNewLine && c == ';' {
|
|
addValue()
|
|
var list *DescriptionList
|
|
var scanIndex int
|
|
scanIndex, list = ParseDescriptionList(text, i+1, depth+1)
|
|
if list != nil {
|
|
if key == "" {
|
|
template.AddParameterUnkeyed(list)
|
|
} else {
|
|
template.AddParameter(key, list)
|
|
}
|
|
}
|
|
lastToken = scanIndex
|
|
i = scanIndex - 1
|
|
} else if afterNewLine && c == ':' {
|
|
addValue()
|
|
lastToken = i + 1
|
|
} else if c == '=' {
|
|
if key == "" {
|
|
addKey()
|
|
lastToken = i + 1
|
|
}
|
|
}
|
|
|
|
if afterNewLine && c != '\n' && c != ' ' && c != '\t' {
|
|
afterNewLine = false
|
|
}
|
|
}
|
|
|
|
return
|
|
}
|