Skip to content

feat(file): carry the name a file already has - #815

Merged
andiwand merged 3 commits into
mainfrom
feat/file-name
Sep 5, 2026
Merged

feat(file): carry the name a file already has#815
andiwand merged 3 commits into
mainfrom
feat/file-name

Conversation

@andiwand

@andiwand andiwand commented Sep 4, 2026

Copy link
Copy Markdown
Member

🤖 Generated with Claude Code

abstract::File knew where a file was but not what it was called. The name
was only reachable through disk_path, which a memory file does not have — so
file_type_by_name (#814) could offer markdown for a .md on disk and nothing
for the same bytes arriving from a download or a browser upload.

Core

  • abstract::File::name(), and the public File::name(): the file's own name,
    without any directory.
    • DiskFile — the basename of its path.
    • MemoryFile — what it was constructed with, empty by default.
    • FileInZip / FileInCfb — the entry name.
  • File::from_memory(std::string data, std::string name = {}) — the new second
    argument is how a caller with bytes and no path says what they were called.
    The default keeps every existing call site compiling and behaving as before.
  • MemoryFile(const abstract::File &) takes the name along with the bytes, so
    reading a file off disk into memory does not forget it is about.odt.
  • open_strategy::file_type_by_name reads the extension off name() rather
    than off disk_path(). A name still only ever adds a candidate the bytes
    already allow, and only for a type no content probe can produce (markdown,
    html) — so File::from_memory(md, "notes.md") now decodes as markdown, and a
    zip called notes.md is still a zip.

Bindings

reads the name names bytes
python File.name() File.from_memory(data, name="")
jni File.name()
apple File.name
wasm Document.fileName odr.open(bytes, { name }), odr.detect(bytes, name)

JNI and Apple never took bytes in the first place — their File is path-only —
so there is nothing to name there beyond what the path, or the archive entry,
already says. The wasm JS wrapper defaults the name, so no existing call
changes; wasm/README.md and the example page now pass the browser's
File.name, which is exactly the case the core change was for.

Testing

  • gtest: File.name_is_the_file_name_on_disk,
    File.from_memory_is_unnamed_unless_told,
    File.a_file_read_into_memory_keeps_its_name,
    File.an_archive_entry_is_named_by_its_entry, and
    odr.a_named_file_in_memory_is_offered_its_type — bytes named notes.md
    list and open as markdown. Full odr_test: 1425 passed, 6 skipped (the same
    6 as on main).
  • pytest 69 passed, JUnit 46 passed, node --test 38 passed, XCTest 26 passed —
    each including the new cases.
  • The changed TUs re-checked with -Wall -Wextra -Wmissing-field-initializers -Werror -fsyntax-only (emscripten's clang for the wasm one); clang-tidy
    reports only findings that pre-date this change.

andiwand and others added 3 commits September 4, 2026 09:33
`abstract::File` knew where a file was but not what it was called. The name was
only reachable through `disk_path`, which a memory file does not have — so
`file_type_by_name` could offer markdown for a `.md` on disk and nothing for the
same bytes uploaded from a browser.

`File::name()` asks the file itself: the file name for one on disk, the entry
name for one inside a zip or cfb, and what `File::from_memory(data, name)` was
given for one in memory, defaulting to none. Reading a file into memory takes
the name with the bytes, so a `MemoryFile` built from a `DiskFile` still knows
it is `about.odt`.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Wana5y5HtzoDq5yMkKvAMS
The name a file carries is only useful where a caller can read it, and where a
caller handing over bytes can set it.

- python: `File.name()`, and `File.from_memory(data, name="")`.
- jni: `File.name()`.
- apple: `File.name`.
- wasm: `open(bytes, {name})` and `detect(bytes, name)` take the browser
  `File.name` the bytes were dropped in under, and `Document.fileName` hands it
  back. The js wrapper defaults it, so no existing call changes.

JNI and Apple never took bytes in the first place — their `File` is a path — so
there is nothing to name there beyond what the path and the archive entry
already say.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Wana5y5HtzoDq5yMkKvAMS
@andiwand
andiwand merged commit 9641b85 into main Sep 5, 2026
24 of 25 checks passed
@andiwand
andiwand deleted the feat/file-name branch September 5, 2026 07:21
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant