diff --git a/.gitignore b/.gitignore index 3bd7ab8..cb2675e 100644 --- a/.gitignore +++ b/.gitignore @@ -16,3 +16,4 @@ compiled/ *.dep /*.bak +/scrbl/*.bak diff --git a/mimetypes.rkt b/mimetypes.rkt index 03f6214..715c7f3 100644 --- a/mimetypes.rkt +++ b/mimetypes.rkt @@ -1,23 +1,65 @@ #lang racket/base -(require racket/contract) +(require racket/contract + racket/string) (provide mimetype-for-ext) -(define/contract (mimetype-for-ext ext) - (-> (or/c string? symbol?) string?) - (hash-ref mimetypes - (if (string? ext) (string->symbol ext) ext) - "application/octet-stream")) +(define mimetype-context/c + (or/c #f + 'application + 'audio + 'example + 'font + 'haptics + 'image + 'message + 'model + 'multipart + 'text + 'video)) + +(define/contract (mimetype-for-ext ext + #:default [default "application/octet-stream"] + #:context [context #f]) + (->* ((or/c path-string? symbol?)) + (#:default string? #:context mimetype-context/c) + string?) + (let* ((extension (normalize-extension ext)) + (types (hash-ref mimetypes extension '()))) + (cond + ((null? types) default) + ((not context) (car types)) + (else + (let ((prefix (string-append (symbol->string context) "/"))) + (or (for/first ((type (in-list types)) + #:when (string-prefix? type prefix)) + type) + default)))))) + +(define (normalize-extension ext) + (let* ((str (cond + ((symbol? ext) (symbol->string ext)) + ((path? ext) (path->string ext)) + (else ext))) + (name (regexp-replace #px"^.*[/\\\\]" str "")) + (match (regexp-match #px"[.]([^.]+)$" name)) + (extension (if match (cadr match) name))) + (string->symbol (string-downcase extension)))) (define mimetypes (make-hash)) (define-syntax addMimeType (syntax-rules () ((_ description http-mimetype extensions description2) - (for-each (λ (mimetype) - (unless (hash-has-key? mimetypes mimetype) - (hash-set! mimetypes mimetype http-mimetype))) + (for-each (λ (extension) + (let* ((key (string->symbol + (string-downcase (format "~a" extension)))) + (types (hash-ref mimetypes key '()))) + (unless (member http-mimetype types) + (hash-set! mimetypes + key + (append types (list http-mimetype)))))) extensions)))) (addMimeType "3D Crossword Plugin" "application/vnd.hzn-3d-crossword" '(x3d) "IANA: 3D Crossword Plugin") @@ -47,13 +89,13 @@ (addMimeType "Adobe Shockwave Player" "application/x-director" '(dir) "Wikipedia: Adobe Shockwave Player") (addMimeType "Adobe XML Data Package" "application/vnd.adobe.xdp+xml" '(xdp) "Wikipedia: XML Data Package") (addMimeType "Adobe XML Forms Data Format" "application/vnd.adobe.xfdf" '(xfdf) "Wikipedia: XML Portable Document Format") -(addMimeType "Advanced Audio Coding (AAC)" "audio/x-aac" '(aac) "Wikipedia: AAC") +(addMimeType "Advanced Audio Coding (AAC)" "audio/aac" '(aac adts loas) "IANA: AAC") (addMimeType "Ahead AIR Application" "application/vnd.ahead.space" '(ahead) "IANA: Ahead AIR Application") (addMimeType "AirZip FileSECURE" "application/vnd.airzip.filesecure.azf" '(azf) "IANA: AirZip") (addMimeType "AirZip FileSECURE" "application/vnd.airzip.filesecure.azs" '(azs) "IANA: AirZip") (addMimeType "Amazon Kindle eBook format" "application/vnd.amazon.ebook" '(azw) "Kindle Direct Publishing") (addMimeType "AmigaDE" "application/vnd.amiga.ami" '(ami) "IANA: Amiga") -(addMimeType "Andrew Toolkit" "application/andrew-inset" '(N/A) "IANA - Andrew Inset") +(addMimeType "Andrew Toolkit" "application/andrew-inset" '() "IANA - Andrew Inset") (addMimeType "Android Package Archive" "application/vnd.android.package-archive" '(apk) "Wikipedia: APK File Format") (addMimeType "ANSER-WEB Terminal Client - Certificate Issue" "application/vnd.anser-web-certificate-issue-initiation" '(cii) "IANA: ANSWER-WEB") (addMimeType "ANSER-WEB Terminal Client - Web Funds Transfer" "application/vnd.anser-web-funds-transfer-initiation" '(fti) "IANA: ANSWER-WEB") @@ -67,9 +109,9 @@ (addMimeType "Assembler Source File" "text/x-asm" '(s) "Wikipedia: Assembly") (addMimeType "Atom Publishing Protocol" "application/atomcat+xml" '(atomcat) "RFC 5023") (addMimeType "Atom Publishing Protocol Service Document" "application/atomsvc+xml" '(atomsvc) "RFC 5023") -(addMimeType "Atom Syndication Format" "application/atom+xml" '(atom xml) "RFC 4287") +(addMimeType "Atom Syndication Format" "application/atom+xml" '(atom) "RFC 4287") (addMimeType "Attribute Certificate" "application/pkix-attr-cert" '(ac) "RFC 5877") -(addMimeType "Audio Interchange File Format" "audio/x-aiff" '(aif) "Wikipedia: Audio Interchange File Format") +(addMimeType "Audio Interchange File Format" "audio/x-aiff" '(aif aiff aifc) "Wikipedia: Audio Interchange File Format") (addMimeType "Audio Video Interleave (AVI)" "video/x-msvideo" '(avi) "Wikipedia: AVI") (addMimeType "Audiograph" "application/vnd.audiograph" '(aep) "IANA: Audiograph") (addMimeType "AutoCAD DXF" "image/vnd.dxf" '(dxf) "Wikipedia: AutoCAD DXF") @@ -190,6 +232,7 @@ (addMimeType "FlashPix" "image/vnd.net-fpx" '(npx) "IANA: FPX") (addMimeType "FLEXSTOR" "text/vnd.fmi.flexstor" '(flx) "IANA: FLEXSTOR") (addMimeType "FLI/FLC Animation Format" "video/x-fli" '(fli) "FLI/FLC Animation Format") +(addMimeType "Free Lossless Audio Codec (FLAC)" "audio/flac" '(flac) "IANA: FLAC") (addMimeType "FluxTime Clip" "application/vnd.fluxtime.clip" '(ftc) "IANA: FluxTime Clip") (addMimeType "Forms Data Format" "application/vnd.fdf" '(fdf) "IANA: Forms Data Format") (addMimeType "Fortran Source File" "text/x-fortran" '(f) "Wikipedia: Fortran") @@ -242,6 +285,10 @@ (addMimeType "H.261" "video/h261" '(h261) "Wikipedia: H.261") (addMimeType "H.263" "video/h263" '(h263) "Wikipedia: H.263") (addMimeType "H.264" "video/h264" '(h264) "Wikipedia: H.264") +(addMimeType "HEIC Image" "image/heic" '(heic) "IANA: HEIC") +(addMimeType "HEIC Image Sequence" "image/heic-sequence" '(heics) "IANA: HEIC Sequence") +(addMimeType "HEIF Image" "image/heif" '(heif hif) "IANA: HEIF") +(addMimeType "HEIF Image Sequence" "image/heif-sequence" '(heifs) "IANA: HEIF Sequence") (addMimeType "Hewlett Packard Instant Delivery" "application/vnd.hp-hpid" '(hpid) "IANA: Hewlett Packard Instant Delivery") (addMimeType "Hewlett-Packard's WebPrintSmart" "application/vnd.hp-hps" '(hps) "IANA: Hewlett-Packard's WebPrintSmart") (addMimeType "Hierarchical Data Format" "application/x-hdf" '(hdf) "Wikipedia: Hierarchical Data Format") @@ -256,7 +303,7 @@ (addMimeType "Hydrostatix Master Suite" "application/vnd.hydrostatix.sof-data" '(sfd-hdstx) "IANA: Hydrostatix Master Suite") (addMimeType "Hyperstudio" "application/hyperstudio" '(stk) "IANA - Hyperstudio") (addMimeType "Hypertext Application Language" "application/vnd.hal+xml" '(hal) "IANA: HAL") -(addMimeType "HyperText Markup Language (HTML)" "text/html" '(html) "Wikipedia: HTML") +(addMimeType "HyperText Markup Language (HTML)" "text/html" '(html htm shtml) "IANA: HTML") (addMimeType "IBM DB2 Rights Manager" "application/vnd.ibm.rights-management" '(irm) "IANA: IBM DB2 Rights Manager") (addMimeType "IBM Electronic Media Management System - Secure Container" "application/vnd.ibm.secure-container" '(sc) "IANA: EMMS") (addMimeType "iCalendar" "text/calendar" '(ics) "Wikipedia: iCalendar") @@ -287,16 +334,15 @@ (addMimeType "Java Bytecode File" "application/java-vm" '(class) "Wikipedia: Java Bytecode") (addMimeType "Java Network Launching Protocol" "application/x-java-jnlp-file" '(jnlp) "Wikipedia: Java Web Start") (addMimeType "Java Serialized Object" "application/java-serialized-object" '(ser) "Java Serialization API") -(addMimeType "Java Source File" "text/x-java-source,java" '(java) "Wikipedia: Java") -(addMimeType "JavaScript" "application/javascript" '(js) "JavaScript") -(addMimeType "JavaScript Module" "text/javascript" '(mjs) "Wikipedia: Javascript") -(addMimeType "JavaScript Module" "text/javascript" '(mjs) "ECMAScript modules") +(addMimeType "Java Source File" "text/x-java-source" '(java) "Apache: Java Source") +(addMimeType "JavaScript" "text/javascript" '(js mjs) "IANA: JavaScript") (addMimeType "JavaScript Object Notation (JSON)" "application/json" '(json) "Wikipedia: JSON") (addMimeType "Joda Archive" "application/vnd.joost.joda-archive" '(joda) "IANA: Joda Archive") -(addMimeType "JPEG Image" "image/jpeg" '(jpeg jpg) "RFC 1314") +(addMimeType "JPEG Image" "image/jpeg" '(jpeg jpg jpe jfif) "IANA: JPEG") (addMimeType "JPEG 2000 Compound Image File Format" "video/jpm" '(jpm) "IANA: JPM") (addMimeType "JPEG Image (Citrix client)" "image/x-citrix-jpeg" '(jpeg jpg) "RFC 1314") (addMimeType "JPEG Image (Progressive)" "image/pjpeg" '(pjpeg) "JPEG image compression FAQ") +(addMimeType "JPEG XL Image" "image/jxl" '(jxl) "IANA: JPEG XL") (addMimeType "JPGVideo" "video/jpeg" '(jpgv) "RFC 3555") (addMimeType "JSON - Linked Data" "application/ld+json" '(jsonld) "Wikipedia: JSON-LD") (addMimeType "Kahootz" "application/vnd.kahootz" '(ktz) "IANA: Kahootz") @@ -328,6 +374,9 @@ (addMimeType "Lucent Voice" "audio/vnd.lucent.voice" '(lvp) "IANA: Lucent Voice") (addMimeType "M3U (Multimedia Playlist)" "audio/x-mpegurl" '(m3u) "Wikipedia: M3U") (addMimeType "M4v" "video/x-m4v" '(m4v) "Wikipedia: M4v") +(addMimeType "Markdown" "text/markdown" '(md markdown) "IANA: Markdown") +(addMimeType "Matroska Audio" "audio/matroska" '(mka) "IANA: Matroska") +(addMimeType "Matroska Video" "video/matroska" '(mkv) "IANA: Matroska") (addMimeType "Macintosh BinHex 4.0" "application/mac-binhex40" '(hqx) "MacMIME") (addMimeType "MacPorts Port System" "application/vnd.macports.portpkg" '(portpkg) "IANA: MacPorts Port System") (addMimeType "MapGuide DBXML" "application/vnd.osgeo.mapguide.package" '(mgp) "IANA: MapGuide DBXML") @@ -435,13 +484,13 @@ (addMimeType "Mophun Certificate" "application/vnd.mophun.certificate" '(mpc) "IANA: Mophun Certificate") (addMimeType "Mophun VM" "application/vnd.mophun.application" '(mpn) "IANA: Mophun VM") (addMimeType "Motion JPEG 2000" "video/mj2" '(mj2) "IANA: MJ2") -(addMimeType "MPEG Audio" "audio/mpeg" '(mpga) "Wikipedia: MPGA") -(addMimeType "MPEG Transport Stream" "video/mp2t" '(ts) "Wikipedia: MPEG Transport Stream") +(addMimeType "MPEG Audio" "audio/mpeg" '(mpga mp2 mp2a mp3 m2a m3a) "IANA: MPEG Audio") +(addMimeType "MPEG Transport Stream" "video/mp2t" '(ts m2t m2ts mts) "IANA: MPEG Transport Stream") (addMimeType "MPEG Url" "video/vnd.mpegurl" '(mxu) "IANA: MPEG Url") -(addMimeType "MPEG Video" "video/mpeg" '(mpeg) "Wikipedia: MPEG") +(addMimeType "MPEG Video" "video/mpeg" '(mpeg mpg mpe m1v m2v) "IANA: MPEG Video") (addMimeType "MPEG-21" "application/mp21" '(m21) "Wikipedia: MPEG-21") -(addMimeType "MPEG-4 Audio" "audio/mp4" '(mp4a) "Wikipedia: MP4A") -(addMimeType "MPEG-4 Video" "video/mp4" '(mp4) "Wikipedia: MP4") +(addMimeType "MPEG-4 Video" "video/mp4" '(mp4 mp4v mpg4) "IANA: MPEG-4 Video") +(addMimeType "MPEG-4 Audio" "audio/mp4" '(m4a mp4a mp4) "IANA: MPEG-4 Audio") (addMimeType "MPEG4" "application/mp4" '(mp4) "RFC 4337") (addMimeType "Multimedia Playlist Unicode" "application/vnd.apple.mpegurl" '(m3u8) "Wikipedia: M3U") (addMimeType "MUsical Score Interpreted Code Invented for the ASCII designation of Notation" "application/vnd.musician" '(mus) "IANA: MUSICIAN") @@ -468,7 +517,7 @@ (addMimeType "Nuera ECELP 9600" "audio/vnd.nuera.ecelp9600" '(ecelp9600) "IANA: ECELP 9600") (addMimeType "Office Document Architecture" "application/oda" '(oda) "RFC 2161") (addMimeType "Ogg" "application/ogg" '(ogx) "Wikipedia: Ogg") -(addMimeType "Ogg Audio" "audio/ogg" '(oga) "Wikipedia: Ogg") +(addMimeType "Ogg Audio" "audio/ogg" '(oga ogg opus spx) "RFC 5334") (addMimeType "Ogg Video" "video/ogg" '(ogv) "Wikipedia: Ogg") (addMimeType "OMA Download Agents" "application/vnd.oma.dd2+xml" '(dd2) "IANA: OMA Download Agents") (addMimeType "Open Document Text Web" "application/vnd.oasis.opendocument.text-web" '(oth) "IANA: OpenDocument Text Web") @@ -505,7 +554,7 @@ (addMimeType "OpenOffice - Writer (Text - HTML)" "application/vnd.sun.xml.writer" '(sxw) "Wikipedia: OpenOffice") (addMimeType "OpenOffice - Writer (Text - HTML)" "application/vnd.sun.xml.writer.global" '(sxg) "Wikipedia: OpenOffice") (addMimeType "OpenOffice - Writer Template (Text - HTML)" "application/vnd.sun.xml.writer.template" '(stw) "Wikipedia: OpenOffice") -(addMimeType "OpenType Font File" "application/x-font-otf" '(otf) "OpenType Font File") +(addMimeType "OpenType Font File" "font/otf" '(otf) "IANA: OpenType") (addMimeType "Opus Audio" "audio/opus" '(opus) "Wikipedia: Opus Audio") (addMimeType "OSFPVG" "application/vnd.yamaha.openscoreformat.osfpvg+xml" '(osfpvg) "IANA: OSFPVG") (addMimeType "OSGi Deployment Package" "application/vnd.osgi.dp" '(dp) "IANA: OSGi Deployment Package") @@ -559,8 +608,8 @@ (addMimeType "QUASS Stream Player" "application/vnd.epson.ssf" '(ssf) "IANA: QUASS Stream Player") (addMimeType "QuickAnime Player" "application/vnd.epson.quickanime" '(qam) "IANA: QuickAnime Player") (addMimeType "Quicken" "application/vnd.intu.qfx" '(qfx) "IANA: Quicken") -(addMimeType "Quicktime Video" "video/quicktime" '(qt) "Wikipedia: Quicktime") -(addMimeType "RAR Archive" "application/x-rar-compressed" '(rar) "Wikipedia: RAR") +(addMimeType "Quicktime Video" "video/quicktime" '(qt mov) "IANA: QuickTime") +(addMimeType "RAR Archive" "application/vnd.rar" '(rar) "IANA: RAR") (addMimeType "Real Audio Sound" "audio/x-pn-realaudio" '(ram) "Wikipedia: RealPlayer") (addMimeType "Real Audio Sound" "audio/x-pn-realaudio-plugin" '(rmp) "Wikipedia: RealPlayer") (addMimeType "Really Simple Discovery" "application/rsd+xml" '(rsd) "Wikipedia: Really Simple Discovery") @@ -576,10 +625,10 @@ (addMimeType "Rich Text Format" "application/rtf" '(rtf) "Wikipedia: Rich Text Format") (addMimeType "Rich Text Format (RTF)" "text/richtext" '(rtx) "Wikipedia: Rich Text Format") (addMimeType "ROUTE 66 Location Based Services" "application/vnd.route66.link66+xml" '(link66) "IANA: ROUTE 66") -(addMimeType "RSS - Really Simple Syndication" "application/rss+xml" '(rss xml) "Wikipedia: RSS") +(addMimeType "RSS - Really Simple Syndication" "application/rss+xml" '(rss) "Wikipedia: RSS") (addMimeType "S Hexdump Format" "application/shf+xml" '(shf) "RFC 4194") (addMimeType "SailingTracker" "application/vnd.sailingtracker.track" '(st) "IANA: SailingTracker") -(addMimeType "Scalable Vector Graphics (SVG)" "image/svg+xml" '(svg) "Wikipedia: SVG") +(addMimeType "Scalable Vector Graphics (SVG)" "image/svg+xml" '(svg svgz) "IANA: SVG") (addMimeType "ScheduleUs" "application/vnd.sus-calendar" '(sus) "IANA: ScheduleUs") (addMimeType "Search/Retrieve via URL Response Format" "application/sru+xml" '(sru) "RFC 6207") (addMimeType "Secure Electronic Transaction - Payment" "application/set-payment-initiation" '(setpay) "IANA: SET Payment") @@ -642,14 +691,14 @@ (addMimeType "System V Release 4 CPIO Checksum Data" "application/x-sv4crc" '(sv4crc) "Wikipedia: pax") (addMimeType "Systems Biology Markup Language" "application/sbml+xml" '(sbml) "RFC 3823") (addMimeType "Tab Seperated Values" "text/tab-separated-values" '(tsv) "Wikipedia: TSV") -(addMimeType "Tagged Image File Format" "image/tiff" '(tiff) "Wikipedia: TIFF") +(addMimeType "Tagged Image File Format" "image/tiff" '(tiff tif) "IANA: TIFF") (addMimeType "Tao Intent" "application/vnd.tao.intent-module-archive" '(tao) "IANA: Tao Intent") (addMimeType "Tar File (Tape Archive)" "application/x-tar" '(tar) "Wikipedia: Tar") (addMimeType "Tcl Script" "application/x-tcl" '(tcl) "Wikipedia: Tcl") (addMimeType "TeX" "application/x-tex" '(tex) "Wikipedia: TeX") (addMimeType "TeX Font Metric" "application/x-tex-tfm" '(tfm) "Wikipedia: TeX Font Metric") (addMimeType "Text Encoding and Interchange" "application/tei+xml" '(tei) "RFC 6129") -(addMimeType "Text File" "text/plain" '(txt) "Wikipedia: Text File") +(addMimeType "Text File" "text/plain" '(txt text conf log) "IANA: Plain Text") (addMimeType "TIBCO Spotfire" "application/vnd.spotfire.dxp" '(dxp) "IANA: TIBCO Spotfire") (addMimeType "TIBCO Spotfire" "application/vnd.spotfire.sfs" '(sfs) "IANA: TIBCO Spotfire") (addMimeType "Time Stamped Data Envelope" "application/timestamped-data" '(tsd) "RFC 5955") @@ -657,7 +706,8 @@ (addMimeType "Triscape Map Explorer" "application/vnd.triscape.mxs" '(mxs) "IANA: Triscape Map Explorer") (addMimeType "troff" "text/troff" '(t) "Wikipedia: troff") (addMimeType "True BASIC" "application/vnd.trueapp" '(tra) "IANA: True BASIC") -(addMimeType "TrueType Font" "application/x-font-ttf" '(ttf) "Wikipedia: TrueType") +(addMimeType "TrueType Font" "font/ttf" '(ttf) "IANA: TrueType") +(addMimeType "TrueType Font Collection" "font/collection" '(ttc) "IANA: Font Collection") (addMimeType "Turtle (Terse RDF Triple Language)" "text/turtle" '(ttl) "Wikipedia: Turtle") (addMimeType "UMAJIN" "application/vnd.umajin" '(umj) "IANA: UMAJIN") (addMimeType "Unique Object Markup Language" "application/vnd.uoml+xml" '(uoml) "IANA: UOML") @@ -677,14 +727,15 @@ (addMimeType "Virtue VTU" "model/vnd.vtu" '(vtu) "IANA: VTU") (addMimeType "Visionary" "application/vnd.visionary" '(vis) "IANA: Visionary") (addMimeType "Vivo" "video/vnd.vivo" '(viv) "IANA: Vivo") -(addMimeType "Voice Browser Call Control" "application/ccxml+xml," '(ccxml) "Voice Browser Call Control: CCXML Version 1.0") +(addMimeType "Voice Browser Call Control" "application/ccxml+xml" '(ccxml) "Voice Browser Call Control: CCXML Version 1.0") (addMimeType "VoiceXML" "application/voicexml+xml" '(vxml) "RFC 4267") (addMimeType "WAIS Source" "application/x-wais-source" '(src) "YoLinux") (addMimeType "WAP Binary XML (WBXML)" "application/vnd.wap.wbxml" '(wbxml) "IANA: WBXML") (addMimeType "WAP Bitamp (WBMP)" "image/vnd.wap.wbmp" '(wbmp) "IANA: WBMP") (addMimeType "Waveform Audio File Format (WAV)" "audio/x-wav" '(wav) "Wikipedia: WAV") (addMimeType "Web Distributed Authoring and Versioning" "application/davmount+xml" '(davmount) "RFC 4918") -(addMimeType "Web Open Font Format" "application/x-font-woff" '(woff) "Wikipedia: Web Open Font Format") +(addMimeType "Web Open Font Format" "font/woff" '(woff) "IANA: WOFF") +(addMimeType "Web Open Font Format 2" "font/woff2" '(woff2) "IANA: WOFF2") (addMimeType "Web Services Policy" "application/wspolicy+xml" '(wspolicy) "W3C Web Services Policy") (addMimeType "WebP Image" "image/webp" '(webp) "Wikipedia: WebP") (addMimeType "WebTurbo" "application/vnd.webturbo" '(wtb) "IANA: WebTurbo") @@ -702,7 +753,8 @@ (addMimeType "X.509 Certificate" "application/x-x509-ca-cert" '(der) "Wikipedia: X.509") (addMimeType "Xfig" "application/x-xfig" '(fig) "Wikipedia: Xfig") (addMimeType "XHTML - The Extensible HyperText Markup Language" "application/xhtml+xml" '(xhtml) "W3C XHTML") -(addMimeType "XML - Extensible Markup Language" "application/xml" '(xml) "W3C XML") +(addMimeType "WebAssembly" "application/wasm" '(wasm) "IANA: WebAssembly") +(addMimeType "XML - Extensible Markup Language" "application/xml" '(xml xsl) "IANA: XML") (addMimeType "XML Configuration Access Protocol - XCAP Diff" "application/xcap-diff+xml" '(xdf) "Wikipedia: XCAP") (addMimeType "XML Encryption Syntax and Processing" "application/xenc+xml" '(xenc) "W3C XML Encryption Syntax and Processing") (addMimeType "XML Patch Framework" "application/patch-ops-error+xml" '(xer) "RFC 5261") @@ -711,14 +763,16 @@ (addMimeType "XML Resource Lists Diff" "application/resource-lists-diff+xml" '(rld) "RFC 4826") (addMimeType "XML Transformations" "application/xslt+xml" '(xslt) "W3C XSLT") (addMimeType "XML-Binary Optimized Packaging" "application/xop+xml" '(xop) "W3C XOP") +(addMimeType "XZ Archive" "application/x-xz" '(xz) "Apache: XZ") (addMimeType "XPInstall - Mozilla" "application/x-xpinstall" '(xpi) "Wikipedia: XPI") (addMimeType "XSPF - XML Shareable Playlist Format" "application/xspf+xml" '(xspf) "XML Shareable Playlist Format") (addMimeType "XUL - XML User Interface Language" "application/vnd.mozilla.xul+xml" '(xul) "IANA: XUL") (addMimeType "XYZ File Format" "chemical/x-xyz" '(xyz) "Wikipedia: XYZ File Format") -(addMimeType "YAML Ain't Markup Language / Yet Another Markup Language" "text/yaml" '(yaml) "YAML: YAML Ain't Markup Language") +(addMimeType "YAML Ain't Markup Language / Yet Another Markup Language" "text/yaml" '(yaml yml) "IANA: YAML") (addMimeType "YANG Data Modeling Language" "application/yang" '(yang) "Wikipedia: YANG") (addMimeType "YIN (YANG - XML)" "application/yin+xml" '(yin) "Wikipedia: YANG") (addMimeType "Z.U.L. Geometry" "application/vnd.zul" '(zir) "IANA: Z.U.L.") (addMimeType "Zip Archive" "application/zip" '(zip) "Wikipedia: Zip") +(addMimeType "Zstandard Archive" "application/zstd" '(zst) "IANA: Zstandard") (addMimeType "ZVUE Media Manager" "application/vnd.handheld-entertainment+xml" '(zmm) "IANA: ZVUE Media Manager") (addMimeType "Zzazz Deck" "application/vnd.zzazz.deck+xml" '(zaz) "IANA: Zzazz") diff --git a/scrbl/.gitignore b/scrbl/.gitignore new file mode 100644 index 0000000..c1fe6a3 --- /dev/null +++ b/scrbl/.gitignore @@ -0,0 +1,3 @@ +/*.css +/*.js +/*.html diff --git a/scrbl/racket-mimetypes.scrbl b/scrbl/racket-mimetypes.scrbl new file mode 100644 index 0000000..0be4959 --- /dev/null +++ b/scrbl/racket-mimetypes.scrbl @@ -0,0 +1,79 @@ +#lang scribble/manual + +@(require (for-label racket/base + racket/contract + racket-mimetypes)) + +@title{MIME Types} +@author[@author+email["Hans Dijkema" "hans@dijkewijk.nl"]] + +@defmodule[racket-mimetypes] + +The @racketmodname[racket-mimetypes] library maps file extensions to MIME type +strings. It uses a built-in table and does not inspect the contents of a file. + +@defproc[(mimetype-for-ext + [ext (or/c path-string? symbol?)] + [#:default default string? "application/octet-stream"] + [#:context context + (or/c #f + 'application + 'audio + 'example + 'font + 'haptics + 'image + 'message + 'model + 'multipart + 'text + 'video) + #f]) + string?]{ + +Returns the MIME type associated with @racket[ext]. The argument can be an +extension, a path string, or a path. Symbols are accepted for extensions. + +The following forms are accepted: + +@itemlist[ + #:style 'compact + @item{A string containing a bare extension, such as @racket["mp3"] or + @racket[".MP3"].} + @item{A symbol containing a bare extension, such as @racket['mp3].} + @item{A string containing a file name or path, such as + @racket["track.flac"], @racket["/music/track.flac"], or + @racket["c:\\music\\track.flac"].} + @item{A Racket path value, such as + @racket[(string->path "/music/track.flac")].} +] + +The final path component is used and the text following its last dot is taken +as the extension. A leading dot on a bare extension is therefore ignored. +Both slash and backslash are recognized as path separators, independent of the +current operating system. The resulting extension is converted to lowercase +and stored internally as a symbol. + +A string without a dot is treated as a bare extension. Consequently, +@racket["README"] is looked up as the extension @racket['readme]. A name ending +in a dot has no recognized extension and normally produces @racket[default]. + +The procedure accepts file-system paths, not URLs. Query strings and fragments +are not removed. The contents of a file are not inspected. + +An extension can have more than one MIME type. Without @racket[context], the +first and most common type is returned. A context selects a MIME type whose +top-level type matches the context. For example, +@racket[(mimetype-for-ext "track.mp4")] returns @racket["video/mp4"], while +@racket[(mimetype-for-ext "track.mp4" #:context 'audio)] returns +@racket["audio/mp4"]. + +If the extension is unknown, or no type matches the supplied context, +@racket[default] is returned. + +For example, @racket[(mimetype-for-ext "MP3")] returns +@racket["audio/mpeg"], @racket[(mimetype-for-ext ".flac")] returns +@racket["audio/flac"], and +@racket[(mimetype-for-ext "unknown" #:default "text/plain")] +returns @racket["text/plain"]. +} diff --git a/tests/mimetypes.rkt b/tests/mimetypes.rkt new file mode 100644 index 0000000..9f356e7 --- /dev/null +++ b/tests/mimetypes.rkt @@ -0,0 +1,39 @@ +#lang racket/base + +(require rackunit + "../main.rkt") + +(check-equal? (mimetype-for-ext 'html) "text/html") +(check-equal? (mimetype-for-ext "MP3") "audio/mpeg") +(check-equal? (mimetype-for-ext ".FLAC") "audio/flac") +(check-equal? (mimetype-for-ext "c:/music/track.MP4") "video/mp4") +(check-equal? (mimetype-for-ext "c:\\music\\track.MP4") "video/mp4") +(check-equal? (mimetype-for-ext (string->path "/music/track.opus")) "audio/ogg") + +(check-equal? (mimetype-for-ext "track.mp4" #:context 'video) "video/mp4") +(check-equal? (mimetype-for-ext "track.mp4" #:context 'audio) "audio/mp4") +(check-equal? (mimetype-for-ext "track.mp4" #:context 'application) "application/mp4") +(check-equal? (mimetype-for-ext "track.mp4" #:context 'image) + "application/octet-stream") + +(check-equal? (mimetype-for-ext "unknown") "application/octet-stream") +(check-equal? (mimetype-for-ext "unknown" #:default "text/plain") "text/plain") + +(check-equal? (mimetype-for-ext "xml") "application/xml") +(check-equal? (mimetype-for-ext "m4a") "audio/mp4") +(check-equal? (mimetype-for-ext "mka") "audio/matroska") +(check-equal? (mimetype-for-ext "mkv") "video/matroska") +(check-equal? (mimetype-for-ext "ogg") "audio/ogg") +(check-equal? (mimetype-for-ext "md") "text/markdown") +(check-equal? (mimetype-for-ext "js") "text/javascript") +(check-equal? (mimetype-for-ext "woff2") "font/woff2") +(check-equal? (mimetype-for-ext "heic") "image/heic") +(check-equal? (mimetype-for-ext "jxl") "image/jxl") +(check-equal? (mimetype-for-ext "zst") "application/zstd") +(check-equal? (mimetype-for-ext "mov") "video/quicktime") +(check-equal? (mimetype-for-ext "tif") "image/tiff") +(check-equal? (mimetype-for-ext "htm") "text/html") +(check-equal? (mimetype-for-ext "m2ts") "video/mp2t") +(check-equal? (mimetype-for-ext "123") "application/vnd.lotus-1-2-3") +(check-equal? (mimetype-for-ext "java") "text/x-java-source") +(check-equal? (mimetype-for-ext "ccxml") "application/ccxml+xml")