package main import ( "html/template" "log" "net/http" "os" "path/filepath" "regexp" "sort" "strings" ) const ( FILES_DIR = "files" TEMPLATES_DIR = "templates" TIME_FORMAT = "Jan 2 2006 15:04:05" ) const ( POST_ICON = "/static/post.gif" FILE_ICON = "/static/file.gif" ) var ( headerPattern = regexp.MustCompile(`(?m)^# (.+)$`) subHeaderPattern = regexp.MustCompile(`(?m)^## (.+)$`) newlinePattern = regexp.MustCompile(`(?m)^([^#<].+)`) boldPattern = regexp.MustCompile(`\*\*(.*?)\*\*|__(.*?)__`) italicPattern = regexp.MustCompile(`\*(.*?)\*|_(.*?)_`) inlineCodePattern = regexp.MustCompile("`([^`]+)`") codeBlockPattern = regexp.MustCompile("(?s)```(.*?)```") blockquotePattern = regexp.MustCompile(`(?m)^> (.+)$`) ulPattern = regexp.MustCompile(`(?m)^(?:-|\*) (.+)$`) olPattern = regexp.MustCompile(`(?m)^\d+\. (.+)$`) linkPattern = regexp.MustCompile(`\[(.*?)\]\((.*?)\)`) ) type FileEntry struct { Name string Timestamp string ParentPath string Icon string } type Page struct { Title string Content template.HTML Files []FileEntry Folders []string BasePath string ParentPath string TimeStamp string } func listEntries(basePath string) ([]FileEntry, []string) { entries, err := os.ReadDir(filepath.Join(FILES_DIR, strings.TrimPrefix(basePath, "/"))) if err != nil { log.Fatal(err) } var files []FileEntry var folders []string for _, entry := range entries { if entry.IsDir() { folders = append(folders, entry.Name()) } else if strings.HasSuffix(entry.Name(), ".md") { info, _ := entry.Info() files = append(files, FileEntry{Name: entry.Name(), Timestamp: info.ModTime().Format(TIME_FORMAT), ParentPath: basePath, Icon: POST_ICON}) }else { info, _ := entry.Info() files = append(files, FileEntry{Name: entry.Name(), Timestamp: info.ModTime().Format(TIME_FORMAT), ParentPath: basePath, Icon: FILE_ICON}) } } sort.Slice(files, func(i, j int) bool { return files[i].Name < files[j].Name }) sort.Strings(folders) return files, folders } func readMarkdown(filename string) string { content, err := os.ReadFile(filepath.Join(FILES_DIR, filename)) if err != nil { log.Fatal(err) } return string(content) } func renderMarkdown(content string) template.HTML { content = headerPattern.ReplaceAllString(content, "

$1

") content = subHeaderPattern.ReplaceAllString(content, "

$1

") content = boldPattern.ReplaceAllString(content, "$1$2") content = italicPattern.ReplaceAllString(content, "$1$2") content = inlineCodePattern.ReplaceAllString(content, "$1") content = codeBlockPattern.ReplaceAllString(content, "
$1
") content = blockquotePattern.ReplaceAllString(content, "
$1
") content = ulPattern.ReplaceAllString(content, "
  • $1
  • ") content = olPattern.ReplaceAllString(content, "
  • $1
  • ") content = linkPattern.ReplaceAllString(content, `$1`) // wrap list items in