#!/usr/bin/env python3 """File-type icons in the style of a desktop file explorer. One source for both web apps: the share site calls icon() from its templates, the admin UI receives kinds() and svgs() as JSON and picks the same SVG in the browser. The icons are drawn here (a page with a coloured badge or glyph) - no vendor logos, no image files, nothing loaded from elsewhere, so they pass the share site's strict Content-Security-Policy. """ from markupsafe import Markup _KIND_EXT = { "word": ("doc", "docx", "docm", "dot", "dotx", "odt", "ott", "rtf", "pages"), "excel": ("xls", "xlsx", "xlsm", "xlsb", "xlt", "xltx", "ods", "ots", "csv", "tsv", "numbers"), "powerpoint": ("ppt", "pptx", "pptm", "pps", "ppsx", "pot", "potx", "odp", "otp", "key"), "pdf": ("pdf",), "image": ("jpg", "jpeg", "png", "gif", "webp", "avif", "heic", "heif", "bmp", "tif", "tiff", "svg", "ico", "raw", "cr2", "cr3", "nef", "arw", "dng", "psd", "xcf"), "video": ("mp4", "m4v", "mkv", "mov", "avi", "wmv", "webm", "mpg", "mpeg", "ts", "m2ts", "3gp", "flv", "ogv"), "audio": ("mp3", "m4a", "aac", "flac", "wav", "ogg", "oga", "opus", "wma", "aiff", "alac", "mid", "midi"), "archive": ("zip", "7z", "rar", "tar", "gz", "tgz", "bz2", "xz", "zst", "iso", "img", "dmg", "cab"), "text": ("txt", "md", "log", "nfo", "ini", "cfg", "conf", "env", "properties", "toml"), "code": ("py", "js", "ts", "jsx", "tsx", "html", "htm", "css", "scss", "json", "yaml", "yml", "xml", "sh", "bash", "ps1", "bat", "cmd", "php", "rb", "go", "rs", "java", "c", "h", "cpp", "hpp", "cs", "sql", "vue", "kt", "swift", "lua", "pl", "dockerfile"), "app": ("exe", "msi", "apk", "deb", "rpm", "appimage", "jar", "dll", "so", "bin"), "mail": ("eml", "msg", "mbox", "vcf", "ics"), } _EXT_KIND = {ext: kind for kind, exts in _KIND_EXT.items() for ext in exts} _PAGE = ('' '') _FONT = 'font-family="Segoe UI,Roboto,Arial,sans-serif" font-weight="700" text-anchor="middle" fill="#fff"' def _badge(color, letters): if len(letters) == 1: return (f'' f'{letters}') return (f'' f'{letters}') _GLYPH = { "word": _badge("#2b579a", "W"), "excel": _badge("#1d7044", "X"), "powerpoint": _badge("#c43e1c", "P"), "pdf": _badge("#d93025", "PDF"), "image": ('' '' ''), "video": ('' ''), "audio": ('' ''), "archive": ('' '' ''), "text": '', "code": (''), "app": ('' ''), "mail": ('' ''), "file": "", } _FOLDER = ('' '') def kind(name, is_dir=False): if is_dir: return "folder" base = str(name or "").lower() ext = base.rsplit(".", 1)[-1] if "." in base else base return _EXT_KIND.get(ext, "file") def svg_for_kind(k): body = _FOLDER if k == "folder" else _PAGE + _GLYPH.get(k, "") return f'' def icon(name, is_dir=False): """Markup for a Jinja template.""" return Markup(svg_for_kind(kind(name, is_dir))) def svgs(): """kind -> SVG, for the admin UI.""" return {k: svg_for_kind(k) for k in list(_GLYPH) + ["folder"]} def ext_kinds(): """extension -> kind, for the admin UI.""" return dict(_EXT_KIND)