package nextcloud import "strings" const ultidocSidecarSuffix = ".ultidoc.json" // IsUltidocSidecarName reports whether name is a TipTap sidecar file. func IsUltidocSidecarName(name string) bool { return strings.HasSuffix(strings.ToLower(strings.TrimSpace(name)), ultidocSidecarSuffix) } func documentBaseName(name string) string { name = strings.TrimSpace(name) if name == "" { return "" } lower := strings.ToLower(name) if strings.HasSuffix(lower, ultidocSidecarSuffix) { return name[:len(name)-len(ultidocSidecarSuffix)] } if i := strings.LastIndex(name, "."); i > 0 { return name[:i] } return name } func sidecarSourceKey(filePath string) string { dir := parentDirPath(filePath) base := strings.ToLower(documentBaseName(fileNameFromPath(filePath))) return dir + "\x00" + base } func parentDirPath(filePath string) string { filePath = NormalizeClientPath(filePath) if filePath == "/" { return "/" } i := strings.LastIndex(filePath, "/") if i <= 0 { return "/" } return filePath[:i] } func fileNameFromPath(p string) string { p = NormalizeClientPath(p) if i := strings.LastIndex(p, "/"); i >= 0 { return p[i+1:] } return p } // FilterHiddenUltidocSidecars removes .ultidoc.json sidecars when the source document // is present in the same listing (sidecar storage mode). Orphan sidecars (overwrite mode) // remain visible. func FilterHiddenUltidocSidecars(files []FileInfo) []FileInfo { if len(files) == 0 { return files } sources := make(map[string]struct{}, len(files)) for _, f := range files { if f.Type == "directory" || IsUltidocSidecarName(f.Name) { continue } sources[sidecarSourceKey(f.Path)] = struct{}{} } out := make([]FileInfo, 0, len(files)) for _, f := range files { if f.Type != "directory" && IsUltidocSidecarName(f.Name) { if _, ok := sources[sidecarSourceKey(f.Path)]; ok { continue } } out = append(out, f) } return out }