Bindery ja asiakirjat ilman liimakoodia

Documents look like files until a real pipeline has to open them. Bindery turns office formats into one Rust engine with detection, normalized APIs, DocQL,...

Bindery ja asiakirjat ilman liimakoodia

Tiedosto ei ollutkaan ongelma

Ensimmäinen virhe on ajatella, että dokumentti on tiedosto. Se saapuu tiedostona, kyllä. Sillä on nimi, yleensä tunniste, joka näyttää rauhoittavalta. Hankintataulukko sanoo .xlsx, raportti sanoo .docx, arkistodumppi sanoo .pdf, ja kaikki teeskentelevät, että maailmasta on tullut yksinkertainen, koska viimeiset neljä merkkiä näyttävät tutuilta. Ihanaa. Sitten tunniste valehtelee, työkirjassa on piilotettuja taulukoita, diaesitys sisältää upotettuja objekteja, PDF on enimmäkseen tekstiä mutta ei aivan, ja vanha Word-tiedosto tuoksuu yhä hienoisesti vuodelta 2003.

Useimmat tiimit eivät rakenna dokumenttiputkea. Ne rakentavat pienen museon formaattipoikkeuksista. Yksi kirjasto Wordille, toinen Excelille, jotain muuta PDF:ille, sankarillinen shell-skripti arkistokansiolle, Python-paketti, jota päivitettiin viimeksi, kun kaikki vielä pitivät QR-koodeja jännittävinä, ja muutama säännöllinen lauseke, jotka pitäisi viedä ulos ja eläköittää hiljaa. Kuusi kuukautta myöhemmin liimakerros on suurempi kuin itse tuote. Tämä ei ole harvinainen virhetila. Tämä on dokumenttityön normaali muoto, kun jokainen formaatti saa oman kuningaskuntansa.

Bindery on olemassa, koska dokumenttikerroksesta ei pitäisi tulla pääprojektia. Toteutustasolla se on Rust-kirjasto nimeltä dweve-bindery. Julkinen sivu kuvailee yhtä kirjastoa, jossa on 17 formaattia, DocQL, Python-sidokset ja yhteinen moottori. Tärkeä osa on, että korkean tason API:t, kuten Document, Presentation ja Workbook, ovat formaattikohtaisten moduulien päällä OLE2:lle, OOXML:lle, ODF:lle, iWorkille, RTF:lle, PDF:lle, Markdownille, EPUB:lle, LaTeXille, kuville, kaavoille ja DocQL:lle. Tämä lista ei ole siellä vaikutuksen tekemistä varten. Se on siellä, koska oikeat korpukset ovat töykeitä.

Hyödyllinen väite on yksinkertainen: avaa dokumentti yhden moottorin kautta, normalisoi mitä voidaan normalisoida ja pidä formaattikohtainen tuska yhteisen pinnan alapuolella. Tämä ei tee kaikista formaateista samanlaisia. Se tekee eroista riittävän selviä, jotta putki selviää niistä.

Bindery alkaa epäilemällä tunnistetta. Tunnistus, jäsennys, normalisointi, kyselyt ja kirjoitus ovat erillisiä tehtäviä, ja juuri siksi liiman ei tarvitse vuotaa kaikkialle.

Tunnistus ei ole koriste

Formaattitunnistus kuulostaa pieneltä apuohjelmalta, kunnes se epäonnistuu. Sitten siitä tulee koko häiriö. Tunnisteet ovat metatietoa, jonka on toimittanut henkilö, työkalu, sähköpostiyhdyskäytävä, vientityö, siirtoskripti tai väsynyt harjoittelija, joka viimeksi koski tiedostoon. Joskus ne ovat oikein. Joskus ne ovat kohtelias ehdotus. Vakavan dokumenttimoottorin pitäisi tarkastaa magic-tavut, säiliön rakenne, pakettiosat, virrat ja sisäiset vihjeet ennen kuin se päättää, mikä lukija omistaa tiedoston.

Bindery kohtelee tätä etuovena. README ja sivu kuvaavat molemmat automaattisen formaattitunnistuksen. Kirjaston dokumentaatio esittää Document::open ja Presentation::open normaalina polkuna, ei juhlallisena valitse-jäsentimesi-seremoniana. Tämä on tärkeää, koska käyttäjät eivät halua dokumenttiarkeologian kurssia ennen kuin voivat poimia taulukon. He haluavat moottorin valitsevan polun ja antavan sitten vakaan API:n.

Tässä on kuiva pieni opetus. Mitä vähemmän glamouria komponentilla on, sitä enemmän vahinkoa se voi tehdä, kun ihmiset heilauttavat sen sivuun. Tunnistus ei ole glamouria. Ei myöskään merkistökoodauksen muunnos, ZIP-käsittely, OLE-hakemiston läpikäynti, suhteiden selvittäminen, Snappy-pakkauksen purku tai XML-nimiavaruuksien käsittely. Hyvä on. Tylsä työ on juuri sitä, missä tuotantoputket joko muuttuvat luotettaviksi tai alkavat kerätä onnenkaluja.

Yksi malli ei tarkoita yhtä valhetta

A unified API can become dangerous when it pretends differences have vanished. Bindery should not claim that a PDF, a spreadsheet, an iWork archive, and an OOXML package are the same animal wearing different hats. They are not. The useful architecture is not to flatten truth into mush. It is to expose common operations where they are common and keep capability boundaries visible where they are not.

The source layout shows that split. There is a unified Word document API, a unified presentation API, spreadsheet traits, formula evaluation behind features, DocQL connectors, and lower-level modules for the formats themselves. The public format matrix says OOXML and ODF are first-class read, write, and query surfaces. PDF and RTF are read-heavy and more careful on writing. EPUB, LaTeX, and Markdown are output formats. Legacy Office and iWork have their own internal machinery. That is the right posture. One engine, yes. One fantasy, no.

This distinction matters in audits and data products. If a compliance workflow extracts clauses from contracts, it must know whether a value came from a paragraph, a table cell, a slide note, a formula, or a PDF text run. If an ingestion job feeds retrieval, it must know whether images, comments, metadata, and relationships were preserved, ignored, or marked as unsupported. The answer cannot be buried inside a parser-specific footnote, because that footnote will not show up when someone asks why the result changed.

A shared engine still needs a capability matrix. The honest promise is not that every format behaves the same. It is that each promise is named and testable.

Documents are structured data that forgot to admit it

The worst thing a document pipeline can do is reduce everything to text too early. Text is useful. Text is not the whole document. A spreadsheet has formulas, references, sheets, rows, cells, number formats, comments, and workbook structure. A presentation has slides, shapes, images, notes, ordering, and sometimes a corporate template that has survived three mergers and one rebrand through sheer malice. A Word document has paragraphs, runs, tables, headers, footers, styles, relationships, and embedded objects. A PDF has streams and layout decisions that may or may not correspond to reading order. Turning all of that into one flat string is fast, comforting, and often wrong.

Bindery’s high-level APIs are useful because they keep document shape alive long enough to ask better questions. The document API exposes paragraphs, runs, tables, rows, and cells. The spreadsheet module exposes workbook and worksheet traits. The formula engine covers a large Excel-compatible function surface. DocQL adds a SQL-like query language over the document model, with lexer, parser, validator, planner, executor, connectors, values, and functions in the source tree. That is more than a convenience wrapper. It is a way to stop rewriting the same extraction logic for every format.

Imagine asking one corpus question: which cells reference this assumption, which tables contain a risk category, which slides mention a policy, which documents have a custom property, and which formulas depend on a given input. In the per-format kingdom, that becomes four scripts and a spreadsheet of apologies. In a shared model, it becomes a query surface. Still work, obviously. Software rarely gifts you a holiday. But it is the right work.

DocQL on ero tekstin kaapimisen ja dokumenttimuotoisten kysymysten esittämisen välillä. Viittaukset, kaavat, taulukot, muodot ja metatiedot pysyvät osana työtä.

Miksi Rust on järkevä valinta tähän sotkuun

Dokumenttiformaatit ovat ihmeellinen yhdistelmä binäärirakenteita, pakattuja paketteja, XML:ää, vanhoja merkistöjä, kuvadataa, päivämääräjärjestelmiä, kaavasemantiikkaa ja tietoturvakysymyksiä. Toisin sanoen sellaista työtä, jossa epämääräinen muistin omistajuus on elämäntapa, johon liittyy laskuja. Rust on järkevä perusta, koska Binderyn on tehtävä huolellista jäsentämistä, hallittava puskureita, käsiteltävä virheet äänekkäästi ja tarjottava rajapintoja, jotka eivät jätä muun pinon arvailtavaksi, mikä meni pieleen.

Crate-ominaisuudet kertovat saman tarinan. Oletusominaisuuksiin kuuluvat OLE, OOXML, OOXML-salaus ja eval-moottori. Täysi tuki ottaa käyttöön iWorkin, ODF:n, RTF:n, kaavat, kuvanmuunnoksen, fontit ja paljon muuta. DocQL on ominaisuus, jolla on oma binääri. Valinnaiset riippuvuudet asettuvat riviin niiden formaattien ja pintojen kanssa, joita ne tukevat: ZIP-käsittely, nopea XML-jäsennys, merkistömuunnos, Snappy, protobuf, kuvan dekoodaus, tilastot ja kompleksiluvut kaavatyötä varten, ja niin edelleen. Tämä ei ole yksi jättimäinen möykky, joka teeskentelee, että jokainen riippuvuus kuuluu kaikkialle. Ominaisuusliput pitävät dokumenttimoottorin muodon näkyvissä.

Sillä on merkitystä upottamisen kannalta. Tietojärjestelmä saattaa haluta täyden toimisto- ja kyselypinnan. Pieni palvelu saattaa haluta vain OOXML:n ja tekstin erottelun. Python-työnkulku saattaa haluta sidokset saman moottorin päälle. Komentorivipohjainen tarkastelupolku voi olla hyödyllinen kertakyselyihin ja testeihin. Sivu puhuu Rustista, PyO3:sta ja CLI-pinnasta; lähdekoodi näyttää DocQL-binäärin ja PyO3-paketin. Tärkeä suunnittelupäätös on, että nämä sisäänmenopisteet istuvat yhden moottorin päällä. Muuten jokaisesta integraatiosta tulee oma hieman erilainen totuutensa, ja sitten bugiraportit alkavat käyttää erilaisia hattuja.

Sisäänmenopisteet voivat erota toisistaan jakamatta totuutta. Rust-rajapintojen, Python-sidosten, DocQL:n ja laajemman Dweve-pinon tulisi käyttää samaa moottoria.

Ylläpitotarina on tuotetarina

Bindery on helppo kuvata jäsentimenä, mutta ylläpitotarina on todellinen tuotetarina. Jokainen putkeen lisätty uusi formaattikirjasto tuo mukanaan oman julkaisurytminsä, bugisanastonsa, virhetyyppinsä, omituisuutensa, riippuvuusriskinsä, testikiinnitteensä ja vikatilansa. Pienessä mittakaavassa se näyttää hallittavalta. Korpusmittakaavassa siitä tulee toiminnallinen arkistokaappi, joka puree.

Jaettu moottori ei poista formaattien monimutkaisuutta. Se olisi epäilyttävää. Se siirtää monimutkaisuuden paikkaan, jossa testejä, ominaisuusmerkintöjä, ominaisuuksia ja rajapintoja voidaan hallita yhdessä. README:ssä on päästä päähän -testejä dokumentti-, esitys-, laskentataulukko-, iWork- ja muille formaateille. Lähdepuussa on moduuleja, jotka tekevät formaattirajat ilmeisiksi. Juuri tämä rakenne antaa tiimille mahdollisuuden parantaa jäsenninkerrosta ilman, että jokaisen tuotetiimin täytyy oppia uudelleen ero suhdeosan ja yhdistelmätiedostovirran välillä.

Tästä syystä Bindery sopii yhteen muun Dweve-pinon kanssa. Reed huolehtii jäsentämisestä kuittien kanssa. BitWeave huolehtii deterministisestä hausta. Fabric ja Spindle huolehtivat hallitusta tiedosta ja operatiivisesta käytöstä. Bindery sijoittuu näiden kerrosten edelle. Se muuttaa toimistoasiakirjat jäsennellyksi materiaaliksi, jota muu pino voi käsitellä. Jos syöttökerros on liimaa ja toivoa, alavirran järjestelmä perii liiman ja toivon. Hyvin tehokasta, jos strateginen tavoitteesi on tuleva kärsimys.

Mitä kysyä ennen käyttöönottoa

Ensimmäinen kysymys ei ole, tukeeko Bindery suosikkitiedostomuotoasi. Se on tarkistuslistakysymys, ja tarkistuslistat ovat hyviä, mutta se ei riitä. Parempi kysymys on, mitä asiakirjalupauksia tarvitset. Tarvitsetko vain luku -poimintaa, kirjoitustukea, pyöreän matkan säilytystä, kaavojen laskentaa, hakua formaattien yli, metatietoja, upotettuja kuvia, salattua OOXML:ää, vanhoja Office-muotoja, iWorkia, ODF:ää tai vientiä EPUBiin, LaTeXiin ja Markdowniin? Nämä ovat erilaisia tehtäviä. Niiden teeskenteleminen yhdeksi tehtäväksi on tapa, jolla tiekartat muuttuvat soppaan.

Toinen kysymys on, miten epäonnistuminen tuodaan esiin. Jos jäsennin ei pysty säilyttämään rakennetta, sanooko se sen? Jos kirjoittaja on parhaansa mukaan toimiva, onko se näkyvissä? Jos kaavaa ei voida laskea, voiko kutsuja päättää, estetäänkö, varoitetaanko vai jatketaanko? Asiakirjamoottori ei ole luotettava siksi, että se ei koskaan sano ei. Se on luotettava, koska sen ei on tyypitetty, täsmällinen ja lähellä ongelmaa.

Kolmas kysymys on, miten testaat omaa aineistoasi. Julkiset esimerkit ovat hyödyllisiä, mutta arkistosi on todennäköisesti oudompi kuin esimerkkikansio. Siinä on rikkinäisiä vientitiedostoja, muinaisia malleja, outoja numeromuotoja, piilotettuja taulukoita, kopioituja taulukoita, virheellisiä PDF-tiedostoja ja tiedostoja nimeltä final_final_really_final. Bindery tarjoaa yhteisen moottorin ja testattavat rajapinnat. Tarvitset silti aineistotestejä. Valitettavasti asiakirjat eivät kasva aikuisiksi itsestään.

Opetus

Binderyn opetus on, että asiakirjojen käsittely ei ole tekstin poimintaa ylimääräisillä vaiheilla. Se on formaatin tunnistusta, rakenteellista jäsentämistä, toimintorajoja, kyselyrajapintoja, kirjoituspolkuja ja ylläpitokuria. Käyttäjä näkee tiedoston. Järjestelmä näkee säiliön, virrat, suhteet, tietueet, tyylit, kaavat, metatiedot, koodaukset ja tulostuslupaukset. Hyvä moottori pitää monimutkaisuuden tuotepinnan alla teeskentelemättä, ettei sitä ole olemassa.

Binderyn tehtävä on tehdä asiakirjakerroksesta tylsä hyvässä mielessä. Yksi Rust-moottori. Korkean tason rajapinnat asiakirjoille, esityksille ja laskentataulukoille. Formaattimoduulit sotkuisia osia varten. DocQL jaettuja kysymyksiä varten. Python- ja pinointegraatio siellä, missä se on hyödyllistä. Toimintotarrat formaattimytologian sijaan.

Tiedosto ei ollut koskaan ongelma. Liima oli. Bindery on yritys lopettaa vuokran maksaminen siitä liimakerroksesta.