4.4 KB
files.go
package sharing

import (
	"fmt"
	"path/filepath"
	"strings"
)

// PathPart represents a breadcrumb segment for navigation.
type PathPart struct {
	Name string
	Path string
}

// ParsePathParts returns breadcrumb parts for a path.
func ParsePathParts(path string) []PathPart {
	if path == "" {
		return nil
	}

	parts := strings.Split(path, "/")
	var result []PathPart
	for i, part := range parts {
		if part == "" {
			continue
		}
		result = append(result, PathPart{
			Name: part,
			Path: strings.Join(parts[:i+1], "/"),
		})
	}
	return result
}

// ParentPath returns the parent directory path.
func ParentPath(path string) string {
	if path == "" {
		return ""
	}
	parent := filepath.Dir(path)
	if parent == "." {
		return ""
	}
	return parent
}

// FileName returns the base name of a path.
func FileName(path string) string {
	return filepath.Base(path)
}

// FileExtension returns the file extension without the leading dot.
func FileExtension(path string) string {
	return strings.TrimPrefix(filepath.Ext(path), ".")
}

// FormatSize formats a file size in human readable format.
func FormatSize(size int64) string {
	if size >= 1048576 {
		return fmt.Sprintf("%.1f MB", float64(size)/1048576.0)
	}
	if size >= 1024 {
		return fmt.Sprintf("%.1f KB", float64(size)/1024.0)
	}
	return fmt.Sprintf("%d B", size)
}

// IsTextFile returns true if the file appears to be a text file.
func IsTextFile(path string) bool {
	name := FileName(path)
	ext := FileExtension(path)

	// Check specific filenames first
	textFiles := map[string]bool{
		"Dockerfile":     true,
		"Makefile":       true,
		"Rakefile":       true,
		"Gemfile":        true,
		"Procfile":       true,
		".gitignore":     true,
		".gitattributes": true,
		".dockerignore":  true,
		".editorconfig":  true,
		".env.example":   true,
		".prettierrc":    true,
		".eslintrc":      true,
		".babelrc":       true,
		"LICENSE":        true,
		"CHANGELOG":      true,
		"AUTHORS":        true,
		"CONTRIBUTORS":   true,
	}
	if textFiles[name] {
		return true
	}

	// Check extensions
	textExtensions := map[string]bool{
		"":          true, // no extension
		"go":        true,
		"js":        true,
		"ts":        true,
		"tsx":       true,
		"jsx":       true,
		"html":      true,
		"css":       true,
		"scss":      true,
		"less":      true,
		"json":      true,
		"yaml":      true,
		"yml":       true,
		"md":        true,
		"txt":       true,
		"sh":        true,
		"bash":      true,
		"zsh":       true,
		"fish":      true,
		"sql":       true,
		"xml":       true,
		"toml":      true,
		"ini":       true,
		"cfg":       true,
		"conf":      true,
		"mod":       true,
		"sum":       true,
		"lock":      true,
		"py":        true,
		"rb":        true,
		"rs":        true,
		"c":         true,
		"h":         true,
		"cpp":       true,
		"hpp":       true,
		"java":      true,
		"kt":        true,
		"swift":     true,
		"php":       true,
		"vue":       true,
		"svelte":    true,
		"env":       true,
		"gitignore": true,
	}
	return textExtensions[ext]
}

// IsMarkdown returns true if the file is a markdown file.
func IsMarkdown(path string) bool {
	ext := FileExtension(path)
	return ext == "md" || ext == "markdown"
}

// PrismLanguage returns the Prism.js language class for syntax highlighting.
func PrismLanguage(path string) string {
	name := FileName(path)
	ext := FileExtension(path)

	// Special filenames
	fileLanguages := map[string]string{
		"Dockerfile":    "docker",
		"Makefile":      "makefile",
		".gitignore":    "gitignore",
		".dockerignore": "gitignore",
		"Gemfile":       "ruby",
		"Rakefile":      "ruby",
	}
	if lang, ok := fileLanguages[name]; ok {
		return lang
	}

	// Extension mapping
	extLanguages := map[string]string{
		"go":     "go",
		"js":     "javascript",
		"ts":     "typescript",
		"tsx":    "tsx",
		"jsx":    "jsx",
		"html":   "html",
		"css":    "css",
		"scss":   "scss",
		"less":   "less",
		"json":   "json",
		"yaml":   "yaml",
		"yml":    "yaml",
		"md":     "markdown",
		"sh":     "bash",
		"bash":   "bash",
		"zsh":    "bash",
		"sql":    "sql",
		"xml":    "xml",
		"toml":   "toml",
		"py":     "python",
		"rb":     "ruby",
		"rs":     "rust",
		"c":      "c",
		"h":      "c",
		"cpp":    "cpp",
		"hpp":    "cpp",
		"java":   "java",
		"kt":     "kotlin",
		"swift":  "swift",
		"php":    "php",
		"vue":    "markup",
		"svelte": "markup",
		"ini":    "ini",
		"env":    "bash",
		"mod":    "go-mod",
	}
	if lang, ok := extLanguages[ext]; ok {
		return lang
	}
	return "plaintext"
}
← Back