mirror of
https://github.com/Dvorinka/MyClubServer.git
synced 2026-06-03 18:22:57 +00:00
143 lines
3.4 KiB
Go
143 lines
3.4 KiB
Go
package controllers
|
|
|
|
import (
|
|
"io/ioutil"
|
|
"net/http"
|
|
"path/filepath"
|
|
"strings"
|
|
|
|
"github.com/gin-gonic/gin"
|
|
)
|
|
|
|
type DocsController struct {
|
|
DocsPath string
|
|
}
|
|
|
|
func NewDocsController(docsPath string) *DocsController {
|
|
return &DocsController{
|
|
DocsPath: docsPath,
|
|
}
|
|
}
|
|
|
|
// GetDocFile serves a specific documentation file
|
|
func (dc *DocsController) GetDocFile(c *gin.Context) {
|
|
// Get the requested file path from the URL
|
|
docPath := c.Param("filepath")
|
|
|
|
// Security: Prevent directory traversal
|
|
if strings.Contains(docPath, "..") {
|
|
c.JSON(http.StatusBadRequest, gin.H{"error": "Invalid file path"})
|
|
return
|
|
}
|
|
|
|
// Build full path
|
|
fullPath := filepath.Join(dc.DocsPath, docPath)
|
|
|
|
// Check if file exists and is a markdown file
|
|
if !strings.HasSuffix(fullPath, ".md") {
|
|
c.JSON(http.StatusBadRequest, gin.H{"error": "Only markdown files are allowed"})
|
|
return
|
|
}
|
|
|
|
// Read the file
|
|
content, err := ioutil.ReadFile(fullPath)
|
|
if err != nil {
|
|
c.JSON(http.StatusNotFound, gin.H{"error": "Documentation file not found"})
|
|
return
|
|
}
|
|
|
|
// Return the content as plain text
|
|
c.Header("Content-Type", "text/markdown; charset=utf-8")
|
|
c.String(http.StatusOK, string(content))
|
|
}
|
|
|
|
// ListDocFiles returns a list of available documentation files
|
|
func (dc *DocsController) ListDocFiles(c *gin.Context) {
|
|
files, err := ioutil.ReadDir(dc.DocsPath)
|
|
if err != nil {
|
|
c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to read documentation directory"})
|
|
return
|
|
}
|
|
|
|
var docFiles []map[string]interface{}
|
|
|
|
for _, file := range files {
|
|
if !file.IsDir() && strings.HasSuffix(file.Name(), ".md") {
|
|
docFiles = append(docFiles, map[string]interface{}{
|
|
"name": file.Name(),
|
|
"path": "/DOCS/" + file.Name(),
|
|
"size": file.Size(),
|
|
"modified_at": file.ModTime(),
|
|
})
|
|
}
|
|
}
|
|
|
|
c.JSON(http.StatusOK, gin.H{
|
|
"files": docFiles,
|
|
"total": len(docFiles),
|
|
})
|
|
}
|
|
|
|
// SearchDocs searches through documentation files
|
|
func (dc *DocsController) SearchDocs(c *gin.Context) {
|
|
query := c.Query("q")
|
|
if query == "" {
|
|
c.JSON(http.StatusBadRequest, gin.H{"error": "Search query is required"})
|
|
return
|
|
}
|
|
|
|
query = strings.ToLower(query)
|
|
files, err := ioutil.ReadDir(dc.DocsPath)
|
|
if err != nil {
|
|
c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to read documentation directory"})
|
|
return
|
|
}
|
|
|
|
var results []map[string]interface{}
|
|
|
|
for _, file := range files {
|
|
if file.IsDir() || !strings.HasSuffix(file.Name(), ".md") {
|
|
continue
|
|
}
|
|
|
|
fullPath := filepath.Join(dc.DocsPath, file.Name())
|
|
content, err := ioutil.ReadFile(fullPath)
|
|
if err != nil {
|
|
continue
|
|
}
|
|
|
|
contentLower := strings.ToLower(string(content))
|
|
nameLower := strings.ToLower(file.Name())
|
|
|
|
// Check if query matches filename or content
|
|
if strings.Contains(nameLower, query) || strings.Contains(contentLower, query) {
|
|
// Find context around match
|
|
index := strings.Index(contentLower, query)
|
|
start := 0
|
|
end := len(content)
|
|
|
|
if index > 100 {
|
|
start = index - 100
|
|
}
|
|
if index+len(query)+200 < len(content) {
|
|
end = index + len(query) + 200
|
|
}
|
|
|
|
excerpt := string(content[start:end])
|
|
|
|
results = append(results, map[string]interface{}{
|
|
"name": file.Name(),
|
|
"path": "/DOCS/" + file.Name(),
|
|
"excerpt": excerpt,
|
|
"matches": strings.Count(contentLower, query),
|
|
})
|
|
}
|
|
}
|
|
|
|
c.JSON(http.StatusOK, gin.H{
|
|
"results": results,
|
|
"total": len(results),
|
|
"query": query,
|
|
})
|
|
}
|