fix: remove duplicated mime types and prefer iana source (#7590)

* fix: remove duplicated mime types and prefer iana source

* refactor: use raw string literals just to be safe

* code review: prefer specific types over octet stream
This commit is contained in:
Yat Ho
2025-05-10 15:59:22 +08:00
committed by GitHub
parent d9a7c3ab94
commit 0fd35eb070
2 changed files with 1289 additions and 1321 deletions

File diff suppressed because it is too large Load Diff

View File

@@ -1,7 +1,8 @@
#!/usr/bin/env node #!/usr/bin/env node
import fs from 'node:fs';
const copyright = const copyright =
`// This file was generated with libtransmission/mime-types.js `// This file was generated with libtransmission/mime-types.js
// DO NOT EDIT MANUALLY // DO NOT EDIT MANUALLY
// This file Copyright © Mnemosyne LLC. // This file Copyright © Mnemosyne LLC.
@@ -9,9 +10,6 @@ const copyright =
// or any future license endorsed by Mnemosyne LLC. // or any future license endorsed by Mnemosyne LLC.
// License text can be found in the licenses/ folder.`; // License text can be found in the licenses/ folder.`;
const fs = require('fs');
const https = require('https');
// https://github.com/jshttp/mime-db // https://github.com/jshttp/mime-db
// > If you're crazy enough to use this in the browser, you can just grab // > If you're crazy enough to use this in the browser, you can just grab
// > the JSON file using jsDelivr. It is recommended to replace master with // > the JSON file using jsDelivr. It is recommended to replace master with
@@ -21,24 +19,49 @@ const https = require('https');
// If the format changes, we'll just update this script. // If the format changes, we'll just update this script.
const url = 'https://cdn.jsdelivr.net/gh/jshttp/mime-db@master/db.json'; const url = 'https://cdn.jsdelivr.net/gh/jshttp/mime-db@master/db.json';
https.get(url, (res) => { async function main() {
res.setEncoding('utf8'); const response = await fetch(url);
const chunks = []; const mime_types = await response.json()
res.on('data', (chunk) => chunks.push(chunk));
res.on('end', () => { const extensions = Object.entries(mime_types)
try { .reduce((acc, [mime_type, info]) => {
const suffixes = []; const { extensions, ...rest } = info;
const mime_types = JSON.parse(chunks.join('')); for (const extension of extensions || [])
for (const [mime_type, info] of Object.entries(mime_types)) { acc.push({ mime_type, extension, info: rest });
for (const suffix of info?.extensions || []) { return acc;
suffixes.push([ suffix, mime_type ]); }, [])
} .sort((lhs, rhs) => {
} // Sort by extension
const extension_order = lhs.extension.localeCompare(rhs.extension);
if (extension_order !== 0)
return extension_order;
// Prefer entries that has a trusted source
const lhs_has_source = lhs.info?.source ? 0 : 1;
const rhs_has_source = rhs.info?.source ? 0 : 1;
const has_source = lhs_has_source - rhs_has_source;
if (has_source !== 0)
return has_source;
// Prefer a specific type over the generic octet stream
const lhs_is_octet = lhs.mime_type === 'application/octet-stream' ? 1 : 0;
const rhs_is_octet = rhs.mime_type === 'application/octet-stream' ? 1 : 0;
const is_octet = lhs_is_octet - rhs_is_octet;
if (is_octet !== 0)
return is_octet;
// Prefer iana source
const lhs_is_iana = lhs.info?.source === 'iana' ? 0 : 1;
const rhs_is_iana = rhs.info?.source === 'iana' ? 0 : 1;
return lhs_is_iana - rhs_is_iana;
})
.filter(({ extension }, pos, arr) => pos === 0 || extension !== arr[pos - 1].extension);
const mime_type_lines = extensions
.map(({ extension, mime_type }) => ` { R"(${extension})", R"(${mime_type})" }`)
.join(',\n')
.trim();
const mime_type_lines = suffixes
.map(([suffix, mime_type]) => ` { "${suffix}", "${mime_type}" }`)
.sort()
.join(',\n');
fs.writeFileSync('mime-types.h', `${copyright} fs.writeFileSync('mime-types.h', `${copyright}
#pragma once #pragma once
@@ -52,13 +75,10 @@ struct mime_type_suffix
std::string_view mime_type; std::string_view mime_type;
}; };
inline auto constexpr MimeTypeSuffixes = std::array<mime_type_suffix, ${suffixes.length}>{ inline auto constexpr MimeTypeSuffixes = std::array<mime_type_suffix, ${extensions.length}>{
{ ${mime_type_lines.trim()} } { ${mime_type_lines} }
}; };
`); `);
} catch (e) { }
console.error(e.message);
}
});
});
main().catch(console.error);