package util import ( "bufio" "fmt" "os" "regexp" "strings" ) // RunTest 运行测试,检测模板 // 标签对{{~}}开头 ,{{end}}结尾 // - {{for .item in .list}} {{end}} // - {{if .bool}}~{{end}} // - {{if .bool}}~{{else}}~{{end}} // - {{if .bool}}~{{elseif}}~{{else}}~{{end}} // // 单标签 // - {{.item}} // 解析模板 func RunTest() { tmpl := ReadFileToString() tags, _ := AnalysisTemplateTags(tmpl) read := Read(tags) fmt.Println(read) } //func CreateFile(tds []TagDouble, tmpl string, data any) string { // //将data 转为map // Decode //} func Read(tags []Tag) []TagDouble { tds := make([]TagDouble, 0) var end TagDouble var i = 0 //首层 for i < len(tags) { end, i = GetEnd(tags, i, len(tags)) if end.IsDoubleTag && len(end.OtherTag) > 0 { end.SubTags = append(end.SubTags, Read(end.OtherTag)...) fmt.Print("") } tds = append(tds, end) } return tds } // GetEnd 结果,返回数组坐标 func GetEnd(tags []Tag, startIndex, endIndex int) (TagDouble, int) { fmt.Println(tags, startIndex, endIndex) sign := 0 otherTags := make([]Tag, 0) head := tags[startIndex] if head.TagType == "ITEM" { return TagDouble{ HeadTag: tags[startIndex], IsDoubleTag: false, EndTag: Tag{}, OtherTag: nil, SubTags: nil, }, startIndex + 1 } for i := startIndex + 1; i < endIndex; i++ { tag := tags[i] if tag.TagType == "IF" || tag.TagType == "FOR" { otherTags = append(otherTags, tag) sign += 1 } else if tag.TagType == "END" { if sign == 0 { return TagDouble{ HeadTag: head, IsDoubleTag: true, EndTag: tag, OtherTag: otherTags, SubTags: nil, }, i + 1 } else { sign -= 1 otherTags = append(otherTags, tag) } } else if tag.TagType == "ITEM" { otherTags = append(otherTags, tag) } else { //panic("其他标签不能作为首标签") } } panic("在咋回事?3") } func IsDoubleHeadTag(Tag Tag) bool { switch strings.ToUpper(Tag.TagType) { case "FOR": return true case "IF": return true case "ELSE": return true case "ELSEIF": return true } return false } type TagDouble struct { HeadTag Tag //头部标签 IsDoubleTag bool //是否为双标签 EndTag Tag //结束标签 OtherTag []Tag //同级并列标签,用于if标签 SubTags []TagDouble //子标签 } func (t TagDouble) String() string { return fmt.Sprintf("TagDouble{HeadTag:%s,IsDoubleTag:%t,EndTag:%s,OtherTag:%s,SubTags:%s}", t.HeadTag.String(), t.IsDoubleTag, t.EndTag.String(), t.OtherTag, t.SubTags) } // AnalysisTemplateTags 解析模板中所有的标签 func AnalysisTemplateTags(tmpl string) ([]Tag, int) { var tags []Tag return FindTag(tmpl, tags, 0) } func FindTag(tmpl string, tags []Tag, startIndex int) ([]Tag, int) { if startIndex == -1 { return tags, -1 } index := FindTagSign(tmpl, startIndex, true) if index == -1 { //完美 return tags, -1 } endIndex := FindTagSign(tmpl, index, false) if endIndex == -1 { return tags, -1 } str := tmpl[index : endIndex+2] //正则判断 if !AllTagReg.MatchString(str) { return tags, -1 } compileRegex := regexp.MustCompile("\\{\\{ *(for|if|elseif|else|end|FOR|IF|ELSEIF|ELSE|END) *.* *}}") matchArr := compileRegex.FindStringSubmatch(str) tag := "ITEM" if len(matchArr) >= 2 { tag = matchArr[1] } tags = append(tags, Tag{ Template: nil, Tag: str, StartIndex: startIndex, EndIndex: endIndex + 2, TagType: strings.ToUpper(tag), }) return FindTag(tmpl, tags, endIndex+2) } //func AnalysisTemplate(tmpl string, startIndex int) (Template, int) { // template := Template{} // index := FindTagSign(tmpl, startIndex, true) // if index == -1 { // //完美 // return template, -1 // } // endIndex := FindTagSign(tmpl, startIndex, false) // if endIndex == -1 { // return template, -1 // } // str := tmpl[index : endIndex+2] // //正则判断 // if AllTagReg.MatchString(str) { // //提取标签 // compileRegex := regexp.MustCompile("\\{\\{ *(for|if|elseif|else|end) +.* *}}") // matchArr := compileRegex.FindStringSubmatch(str) // // template.TagType = matchArr[1] // //匹配到 // template.Tag = Tag{ // Template: &template, // tag: "", // StartIndex: 0, // EndIndex: 0, // TagType: "", // } // template.Content = tmpl[index+2 : endIndex] // return template, endIndex + 2 // } // return Template{}, index //} // FindTagSign 查找模板头部 todo 如果后续需要做转义处理,可以在这里完成 func FindTagSign(tmpl string, startIndex int, isHead bool) int { if isHead { return IndexOf(tmpl, "{{", startIndex) } return IndexOf(tmpl, "}}", startIndex) } func IndexOf(s, subString string, startIndex int) int { str := s[startIndex:] index := strings.Index(str, subString) if index == -1 { return -1 } return index + startIndex } func ReadFileToString() string { file, err := os.OpenFile("./service/struct.go.template", os.O_CREATE|os.O_RDWR, 0666) if err != nil { panic(err) } defer file.Close() reader := bufio.NewReader(file) var bytes = make([]byte, 1024) var strBytes = make([]byte, 0) for { n, err := reader.Read(bytes) if err != nil { panic(err) } strBytes = append(strBytes, bytes[:n]...) if n < 1024 { break } } return string(strBytes) }