feat(panel): the file editor opens anything that is text, not a list of extensions - #131
Merged
Merged
Conversation
…of extensions The editor was reached through an allow list of fourteen extensions, and it behaved as an allow list does. A folder of Garry's Mod `.lua` offered nothing but downloads; so did a Skript `.sk`, a datapack `.mcfunction`, a Python bot, a `Dockerfile`, a `.env`. All of it plain text, all of it refused because nobody had thought to name it, and no way for the person looking at the file to say "open it anyway". The rule is now the other way round, and split between the two places that can answer it honestly. **The name only rules things out.** `BINARY_FILE_EXTENSIONS` names what is certainly not text — archives, images, sounds, compiled code, databases, a game's world data — and everything else goes to the editor, including a file with no extension at all. It lives in `@hopper/shared` next to `MAX_EDITABLE_FILE_BYTES`, since the front end and the daemon have to agree on it. **The bytes decide.** `files/contents` reads the first 8000 bytes and answers 415 `file_not_text` when a NUL byte is in them — git's heuristic, and chosen for being narrow: refusing invalid UTF-8 instead would refuse the Latin-1 `server.properties` that a decade of Minecraft servers are full of, which is a file people legitimately edit. The head is read separately from the stream that serves the file, because the answer is needed before the reply is sent and a stream already being sent can no longer change its status code. The editor turns that refusal into a sentence and a download link rather than a status code, in the five languages. Two strings that had stayed in French on that page are translated with it. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01HiQhbiTpvjFnK7CJcJuR9m
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Ouvrir un dossier de
.luaGarry's Mod dans le gestionnaire de fichiers ne proposait que des téléchargements. La page d'édition existait pourtant déjà — c'est la porte qui était fermée :Quatorze extensions, et une liste d'autorisation se comporte comme une liste d'autorisation.
.lua,.skd'un Skript,.mcfunctiond'un datapack, un bot Python, unDockerfile, un.env: du texte parfaitement éditable, refusé parce que personne n'avait pensé à l'inscrire, et aucun moyen pour la personne qui regarde le fichier d'insister.La règle est inversée, et coupée en deux entre les endroits qui peuvent répondre honnêtement.
Le nom ne sert plus qu'à écarter
BINARY_FILE_EXTENSIONSnomme ce qui n'est certainement pas du texte — archives, images, sons, code compilé, bases de données, données de monde d'un jeu. Tout le reste va à l'éditeur, y compris un fichier sans aucune extension. La constante vit dans@hopper/shared, à côté deMAX_EDITABLE_FILE_BYTES: le front et le daemon doivent s'accorder dessus.Les octets tranchent
files/contentslit les 8000 premiers octets et répond 415file_not_textsi un octet NUL s'y trouve.C'est l'heuristique de git, et elle est choisie pour être étroite. Refuser l'UTF-8 invalide à la place refuserait le
server.propertiesen Latin-1 dont une décennie de serveurs Minecraft est remplie — un fichier que les gens éditent légitimement et qu'aucun autre outil n'a jamais contesté. Un octet NUL, lui, n'apparaît dans aucun texte que quelqu'un a voulu écrire.La tête est lue séparément du flux qui sert le fichier : la réponse est nécessaire avant l'envoi, et un flux déjà parti ne peut plus changer son code de statut. Réenfiler le morceau déjà consommé devant le flux aurait mis un emballage entre Fastify et le descripteur — c'est lui qui le referme quand un client raccroche en cours de route.
Et quand ça arrive quand même
L'éditeur transforme le refus en une phrase et un lien de téléchargement, dans les cinq langues, plutôt qu'en code de statut. Deux chaînes restées en français sur cette page sont traduites au passage.
Vérifié
Six tests sur
packages/shared(le prédicat, dont le Latin-1 et le fichier vide) et six nouveaux sur la route du daemon —apps/daemon/src/routes/files.spec.ts, contre un vrai système de fichiers temporaire : un.luaservi en 200, unDockerfileaussi, un fichier à NUL refusé en 415, du Latin-1 servi, un fichier vide servi, un dossier toujours refusé en 400.format:check,lint7/7,typecheck7/7,build5/5,test7/7.🤖 Generated with Claude Code
https://claude.ai/code/session_01HiQhbiTpvjFnK7CJcJuR9m