Files
orca/src/shared/binary-file-extensions.ts
T
Brennan Benson 40820c4c5c Open pasted text in structured chats (#35636)
* Open large pasted text and attached text in structured chats

* Read pending pasted text before its host route resolves

* Pass structured attachment eligibility from the owning chat

* Preserve composer and Markdown state when inspecting text attachments

* fix: preserve attachment identity and cancel deferred reads

* test: consolidate phone attachment rendering contracts

* Scope attachment previews to visible chats and share route indexes

* test: consolidate duplicate attachment preview coverage

* perf: share remaining workspace catalog derivations

* feat(chat): open text attachments from structured goal objectives

* fix(chat): reuse preview owner and bind app hooks

* refactor(chat): trim duplicate tests and unused capability initialization

* test(chat): share routing scope mount fixture

* Fix routing performance attribution and folder row imports

* Share attachment capability through its domain module

* Align attachment fixtures and warm routing contracts with current gates

* Preserve relay connection timeout default for ordinary requests

* Share image classification ownership and repair integration fixtures

* Repair real attachment integration fixture boundaries

* Expose e2e compiler diagnostics and prune stale read allowance

* Type the recall fixture row ref as a div

* Keep text attachment capability in its existing capability owner

* Keep image MIME bindings in the media type owner

* Own private bridge response completion at the request boundary

* Complete bridge fixture return and retention types

* Localize native chat text attachment preview controls

* Complete attachment preview localization at presentation boundaries

* Preserve legacy preview locale identity and complete localization controls

* Fix typed mobile host witness lookup

* Commit attachment page edits and reset mobile page scroll

* test(chat): remove duplicate preview localization coverage

* fix(mobile): apply page input font and footer safe area

* fix(chat): commit edited page before admitted navigation

* fix(chat): retain field readiness on pending commit

* fix: preserve attachment field focus until control activation

* fix: restore attachment preview styles and canonical close

* Bind mobile input font role to the central theme

* Type font source fixture cases as tuples

* Attribute inherited owner filter work and qualify folder fixtures

* Keep owner filter fixture input types source-derived

* test: retain attachment capability assertion import

* test: focus attachment coverage on important regressions

* Replace text attachment paging with bounded scrolling and trim tests

* Preserve literal phone attachment whitespace and trim unused test meter

* Keep scroll view refs and measurements out of render

* Keep preview collection independent of native clipboard initialization

* Give the phone scroll fixture coherent measured DOM geometry

* Commit attachment scroll extent before restoring its anchor

* Preserve text viewport geometry across bounded reads

* Unify bounded text scrolling around the viewport

* Preserve the live text anchor across viewport resizing

* Measure committed text viewport bounds from the host

* Preserve live attachment position across native client extent changes

* Use the actual first source block in the resize regression fixture

* Reuse subscription handle type

* Keep attachment effects keyed to their existing triggers

* Keep attachment rows within the committed track

* Allow the full attachment renderer contract to settle

* Open text attachment previews in a large modal

* Preserve attachment modal header layout with primitive-owned styles
2026-11-02 18:36:29 -08:00

89 lines
1.8 KiB
TypeScript

import { IMAGE_FILE_EXTENSIONS } from './media-file-extensions'
export { IMAGE_FILE_MIME_TYPES, IMAGE_FILE_EXTENSIONS } from './media-file-extensions'
// Keep SVG out of binary extensions because editors open it as source text.
const TEXT_IMAGE_EXTENSIONS = new Set(['.svg'])
const NON_IMAGE_BINARY_EXTENSIONS = [
// Archives
'.7z',
'.bz2',
'.gz',
'.jar',
'.rar',
'.tar',
'.tgz',
'.war',
'.xz',
'.zip',
'.zst',
// Audio and video
'.aac',
'.avi',
'.flac',
'.m4a',
'.mkv',
'.mov',
'.mp3',
'.mp4',
'.ogg',
'.wav',
'.webm',
// Documents
'.doc',
'.docx',
'.pdf',
'.ppt',
'.pptx',
'.xls',
'.xlsx',
// Fonts
'.eot',
'.otf',
'.ttc',
'.ttf',
'.woff',
'.woff2',
// Compiled artifacts and datastores
'.a',
'.bin',
'.class',
'.dll',
'.dylib',
'.exe',
'.idx',
'.lockb',
'.node',
'.o',
'.pack',
'.pyc',
'.pyd',
'.so',
'.sqlite',
'.sqlite3',
'.wasm'
]
export const BINARY_FILE_EXTENSIONS: readonly string[] = Object.freeze([
...IMAGE_FILE_EXTENSIONS.filter((extension) => !TEXT_IMAGE_EXTENSIONS.has(extension)),
...NON_IMAGE_BINARY_EXTENSIONS
])
const BINARY_FILE_EXTENSION_SET = new Set(BINARY_FILE_EXTENSIONS)
/** Guess by extension only without bytes; use isBinaryBuffer for content-based detection. */
export function hasBinaryFileExtension(filePath: string | undefined): boolean {
if (filePath === undefined) {
return false
}
const lowerPath = filePath.toLowerCase()
const dotIndex = lowerPath.lastIndexOf('.')
const separatorIndex = Math.max(lowerPath.lastIndexOf('/'), lowerPath.lastIndexOf('\\'))
// A leading dot is a dotfile (.gitignore), not an extension.
if (dotIndex <= separatorIndex + 1) {
return false
}
return BINARY_FILE_EXTENSION_SET.has(lowerPath.slice(dotIndex))
}