code.js 1.5 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455
  1. const RENDERER_GROUPS = {
  2. document: ['doc', 'docx', 'pdf', 'ofd', 'typ', 'typst'],
  3. sheet: ['xlsx', 'xls', 'csv', 'ods'],
  4. drawing: ['dxf', 'dwg', 'dwf', 'dwfx', 'xps'],
  5. source: ['js', 'ts', 'tsx', 'vue', 'json', 'yaml']
  6. }
  7. const DEFAULT_ICON = {
  8. label: 'FILE',
  9. tone: '#64748b'
  10. }
  11. function normalizeExtension(filename = '') {
  12. const cleanName = filename.split('?')[0].split('#')[0]
  13. const dotIndex = cleanName.lastIndexOf('.')
  14. return dotIndex >= 0 ? cleanName.slice(dotIndex + 1).toLowerCase() : ''
  15. }
  16. export function resolvePreviewMeta(filename) {
  17. const extension = normalizeExtension(filename)
  18. for (const [group, extensions] of Object.entries(RENDERER_GROUPS)) {
  19. if (extensions.includes(extension)) {
  20. return {
  21. group,
  22. extension,
  23. icon: extension.toUpperCase(),
  24. supported: true
  25. }
  26. }
  27. }
  28. return {
  29. group: 'unknown',
  30. extension,
  31. icon: DEFAULT_ICON.label,
  32. supported: false
  33. }
  34. }
  35. export async function createPreviewFile(url, fallbackName = 'download.bin') {
  36. const response = await fetch(url, { credentials: 'include' })
  37. if (!response.ok) {
  38. throw new Error(`Download failed with ${response.status}`)
  39. }
  40. const blob = await response.blob()
  41. const name = decodeURIComponent(url.split('/').pop() || fallbackName)
  42. return new File([blob], name, { type: blob.type })
  43. }
  44. const samples = ['invoice.ofd', 'report.typ', 'drawing.dxf', 'component.vue', 'archive.unknown']
  45. const summary = samples.map(resolvePreviewMeta)
  46. console.table(summary)