82 lines
1.8 KiB
Go
82 lines
1.8 KiB
Go
package emdbed
|
|
|
|
import (
|
|
"fmt"
|
|
"io"
|
|
"os"
|
|
"path/filepath"
|
|
"regexp"
|
|
"strings"
|
|
)
|
|
|
|
var (
|
|
start = regexp.MustCompile(`(?m)^<!--\s*emdbed:\s*([^\s]+)\s*(~[\w]+)?\s*(?:(/[^/]+/|L\d+)\s*(/[^/]+/|L\d+)?)?\s*-->$`)
|
|
end = regexp.MustCompile(`(?m)^<!--\s*/emdbed\s*-->$`)
|
|
)
|
|
|
|
// ConvertFile is a helper for converting a file on disk
|
|
func ConvertFile(path string) (string, error) {
|
|
fi, err := os.Open(path)
|
|
if err != nil {
|
|
return "", err
|
|
}
|
|
defer fi.Close()
|
|
return Convert(filepath.Dir(path), fi)
|
|
}
|
|
|
|
// Convert converts an io.Reader with respect to a base directory
|
|
func Convert(dir string, file io.Reader) (string, error) {
|
|
data, err := io.ReadAll(file)
|
|
if err != nil {
|
|
return "", err
|
|
}
|
|
contents := string(data)
|
|
|
|
var out strings.Builder
|
|
starts := start.FindAllStringSubmatchIndex(contents, -1)
|
|
ends := end.FindAllStringIndex(contents, -1)
|
|
if len(starts) != len(ends) {
|
|
return "", fmt.Errorf("start selectors (%d) != end selectors (%d)", len(starts), len(ends))
|
|
}
|
|
var last int
|
|
for idx, start := range starts {
|
|
out.WriteString(contents[last:start[1]])
|
|
|
|
relPath := contents[start[2]:start[3]]
|
|
fileContents, err := os.ReadFile(filepath.Join(dir, relPath))
|
|
if err != nil {
|
|
return "", err
|
|
}
|
|
|
|
lang := strings.TrimPrefix(filepath.Ext(relPath), ".")
|
|
if start[4] != -1 {
|
|
lang = contents[start[4]+1 : start[5]]
|
|
}
|
|
|
|
var startSel string
|
|
if start[6] != -1 {
|
|
startSel = contents[start[6]:start[7]]
|
|
}
|
|
var endSel string
|
|
if start[8] != -1 {
|
|
endSel = contents[start[8]:start[9]]
|
|
}
|
|
|
|
e := emdbed{
|
|
name: relPath,
|
|
contents: string(fileContents),
|
|
language: lang,
|
|
start: startSel,
|
|
end: endSel,
|
|
}
|
|
sel, err := e.Selection()
|
|
if err != nil {
|
|
return "", err
|
|
}
|
|
out.WriteString(fmt.Sprintf("\n```%s\n%s\n```\n", e.language, sel))
|
|
last = ends[idx][0]
|
|
}
|
|
out.WriteString(contents[last:])
|
|
return out.String(), nil
|
|
}
|