package parser
import (
"bufio"
"fmt"
"os"
"path/filepath"
"regexp"
"strings"
)
var (
commentRegexps []*regexp.Regexp
sectionRegexps []*regexp.Regexp
continuationRegexps []*regexp.Regexp
captureRegexps []*regexp.Regexp
)
// !MAN: Node Style getter/setter
// Option 1: (2 args) .Style("background","yellow") -> "" -- Sets the inline value of background
// Option 2: (1 args) .Style("background") -> "" -- Gets the inline value of background
// Option 3: (0 args) .Style("background") -> "" -- Returns all inline styles as a string
// [!DEVMAN]Note: Contains all user inputed styles, all inline styles over ride stylesheet styles
func init() {
commentPatterns := []string{
`^\s*//\s*!(\w+(?:,\w+)*):\s*(.*)$`, `^\s*# !(\w+):\s*(.*)$`, `^\s*; !(\w+):\s*(.*)$`, `^\s*% !(\w+):\s*(.*)$`,
`^\s*-- !(\w+):\s*(.*)$`, `^\s*/\* !(\w+):\s*(.*)\*/`, `^\s*`,
}
sectionPatterns := []string{
`^\s*//\s*(?:\+\s*(?:\[([!?\w,]+)\](\w+)|(\w+))):\s*(.*)$`, `^\s*# \+\s*(\w+):\s*(.*)$`, `^\s*; +\s*(\w+):\s*(.*)$`, `^\s*% \+\s*(\w+):\s*(.*)$`,
`^\s*-- \+\s*(\w+):\s*(.*)$`, `^\s*/\* \+\s*(\w+):\s*(.*)\*/`, `^\s*`,
}
continuationPatterns := []string{
`^\s*// \+\s*(.*)$`, `^\s*# \+\s*(.*)$`, `^\s*; \+\s*(.*)$`, `^\s*% \+\s*(.*)$`,
`^\s*-- \+\s*(.*)$`, `^\s*/\* \+\s*(.*)\*/`, `^\s*`,
}
for i := range commentPatterns {
commentRegexps = append(commentRegexps, regexp.MustCompile(commentPatterns[i]))
sectionRegexps = append(sectionRegexps, regexp.MustCompile(sectionPatterns[i]))
continuationRegexps = append(continuationRegexps, regexp.MustCompile(continuationPatterns[i]))
}
}
type Comment struct {
Headers []string
Data []string
Tags []string
File string
Line int
Capture string
}
func File(path string) []Comment {
file, err := os.Open(path)
if err != nil {
fmt.Println("Error opening file:", path, err)
return []Comment{}
}
defer file.Close()
scanner := bufio.NewScanner(file)
lines := []string{}
for scanner.Scan() {
lines = append(lines, scanner.Text())
}
return Text(path, lines)
}
func Text(path string, lines []string) []Comment {
comments := []Comment{}
var currentComment *Comment
captureIndexes := []int{}
currentMatches := false
for lineNumber, line := range lines {
for i := range commentRegexps {
if len(captureIndexes) > 0 {
for _, v := range captureIndexes {
if !strings.HasSuffix(comments[v].Capture, line+"\n") {
comments[v].Capture += line + "\n"
}
}
}
if matches := commentRegexps[i].FindStringSubmatch(line); matches != nil {
if currentComment != nil {
comments = append(comments, *currentComment)
if currentMatches {
captureIndexes = append(captureIndexes, len(comments)-1)
}
currentMatches = false
}
tags := strings.Split(strings.TrimSpace(matches[1]), ",")
currentComment = &Comment{
File: path,
Line: lineNumber,
Tags: tags,
Headers: []string{tags[0]},
Data: []string{strings.TrimSpace(matches[2])},
}
if strings.Contains(strings.Join(currentComment.Data, ""), "@") {
currentMatches = true
}
break
} else if matches := sectionRegexps[i].FindStringSubmatch(line); matches != nil {
if currentComment != nil {
label := matches[2]
if label == "" {
label = matches[3]
}
if label == "" {
label = "[" + matches[1] + "]" + matches[2]
}
// this is sjda test
currentComment.Headers = append(currentComment.Headers, label)
currentComment.Data = append(currentComment.Data, matches[4])
if strings.Contains(strings.Join(currentComment.Data, ""), "@") {
currentMatches = true
}
}
break
} else if matches := continuationRegexps[i].FindStringSubmatch(line); matches != nil {
if currentComment != nil {
currentComment.Data[len(currentComment.Data)-1] += "\n" + matches[1]
if strings.Contains(strings.Join(currentComment.Data, ""), "@") {
currentMatches = true
}
}
break
} else if currentComment != nil {
comments = append(comments, *currentComment)
currentComment = nil
if currentMatches {
captureIndexes = append(captureIndexes, len(comments)-1)
}
currentMatches = false
}
}
}
return comments
}
func LoadPaths(root string) []string {
paths := []string{}
err := filepath.Walk(root, func(path string, info os.FileInfo, err error) error {
if err != nil {
return nil
}
if strings.Contains(path, ".git") {
return nil
}
if !info.IsDir() {
paths = append(paths, path)
}
return nil
})
if err != nil {
fmt.Println("Error walking path:", err)
}
return paths
}