Aller au contenu principal

appcore-filemaker

BÊTA PUBLIQUE0.1.0-beta.2 est publiée sur crates.io pour évaluation.

appcore-filemaker 0.1.0-beta.2 est le compilateur déterministe officiel d'AppCore pour documents déclaratifs, canvases vectoriels et datasets. La version 0.1.0-beta.2 est publiée sur crates.io et reste hors du Runtime stable.

Pour découvrir le format, suivez le guide YAML pas à pas. Il part de l'en-tête minimal puis couvre données, styles, vecteurs, tables, rôles de page, images, collision, composants et preflight strict. Il se termine par la référence complète des champs et distingue les nœuds réservés non encore implémentés.

Le YAML strict filemaker: "1.0", les données typées et patches atomiques sont compilés en IR. Polices et assets explicites sont mesurés avant layout fixed-point, collision/reflow géométrique et construction de la ResolvedScene immuable. Inspection, validation, preflight et export consomment cette scène sans modifier la géométrie.

Canvas est un contrat de dessin sémantique, pas un tampon de pixels. Les coordonnées acceptent pt, px, mm, cm, in, %, l'unité logique lu et les valeurs norm/normalized bornées à 0..=1. Text, image, line, rect, circle, ellipse, polygon, path et group restent des nœuds typés ; les paths conservent move, line, courbe cubique et close. Circle exige des axes résolus égaux. Safe area, presets, layers/z-index, transforms et collision sont des entrées explicites et orthogonales.

Les couleurs restent indépendantes du format en RGB, RGBA, Gray ou CMYK en millionièmes. YAML accepte noms stables, hex, notation fonctionnelle entière et couleurs typées avec tag explicite ; fonds fill, bordures stroke et opacity restent séparés. MemoryResolver et FileResolver à racine canonique implémentent la résolution bornée des assets, templates et polices. FontManager::register_from enregistre une police logique exacte sous la limite d'octets de l'appelant sans jamais parcourir les polices de l'hôte. L'ordre explicite de fallback fait partie du fingerprint. SVG et HTML incorporent les familles réellement choisies dans les glyph runs résolus, y compris les cellules de table.

La cascade complète est defaults → theme → template → style component/nommé/inline développé → règles data conditionnelles ordonnées → SetStyle runtime transactionnel → ExportStyleOverride. Le style runtime change avant la mesure. La couche export expose seulement fill, stroke, opacity et couleur texte ; elle ne peut invalider la géométrie résolue. Layer, z-index et ordre source trient la peinture indépendamment de la collision géométrique.

Les métadonnées raster et SVG sont résolues avant export. contain et la réduction scale_down conservent l'aspect en microunités fixed-point ; fill, none intrinsèque, crop, cover focal et EXIF facultatif produisent des rectangles source, destination et clip immuables. Preflight calcule le DPI raster effectif après transform. SVG/HTML incorporent SVG ; PDF/raster signalent sa rasterisation non prise en charge comme perte de fidélité explicite.

La politique de collision hérite dans l'ordre explicite document → page → région → groupe → élément. Le YAML accepte collision: false, et le reflow interroge le bound mesuré sélectionné : layout, visuel ou intrinsèque.

Les transforms fixed-point prennent en charge translation, rotation en degrés entiers, échelle, flip/mirror et origins explicites. Ils se composent dans les groupes ; PDF, SVG, PNG/JPEG et HTML consomment la même matrice résolue.

Les éléments texte déclarent le layout via text_options. L'overflow accepte wrap, shrink, ellipsis, clip, expand et error, avec max_lines borné, min_font_size absolu et line_height fixed-point. Mesure et expansion précèdent la collision ; le clipping est une géométrie résolue ; SVG et HTML rendent les runs façonnés/tronqués. writing_mode: vertical implémente des colonnes de haut en bas progressant de droite à gauche en PDF, SVG, PNG/JPEG et HTML. L'emoji couleur reste une perte explicite jusqu'à son implémentation.

La géométrie déclarative traverse aussi YAML et IR sans modification. constraints porte minimum, préféré, maximum et ratio largeur/hauteur fixed-point ; align_x et align_y choisissent début, centre ou fin dans le conteneur actif. Les anchors ciblent les bords d'éléments antérieurs ou des guides nommés avec guide:nom[+offset]. Coordonnées, plages et ratios contradictoires échouent explicitement. Les patches move/resize remplacent l'intention de position/taille antérieure.

Les conteneurs flow verticaux et horizontaux acceptent start, center, end, space_between, space_around et space_evenly. Toute distribution autre que start exige une taille primaire explicite, préférée ou dérivée du ratio ; mesure auto ambiguë et overflow échouent avant la collision. La planification des flux distribués compte les enfants visibles en deux passes bornées, sans allouer de liste temporaire de références et en conservant le même espacement. Le fingerprint trie les références empruntées aux noms d'assets, évitant les chaînes clonées pendant la résolution déterministe.

Les exclusions nommées au niveau racine définissent des rectangles relatifs à la page, non peints et obligatoirement contenus dans la trim box. Elles se répètent dans le budget géométrique global et initialisent l'index spatial de chaque page physique avant le placement des éléments. Les champs optionnels group et collides_with utilisent le même contrat de collision symétrique que les éléments, tandis que la politique push/error/next-page/shrink du candidat reste responsable du reflow borné. Inspection, masques de collision et requêtes de régions libres conservent l'exclusion résolue ; les exporters ne reçoivent aucun node à peindre.

Les pages document peuvent déclarer des layers master, first, continuation et last, chacune divisée en bandes background, header et footer sans collision. Les éléments master se répètent sur chaque page physique ; une layer de rôle est choisie après la pagination bornée du corps ; et le texte {page}/{pages} n'est résolu qu'une fois le total final connu. Composants, styles, binding, patches, inspection et tous les exporters de scène respectent le même contrat. Les éléments résolus conservent un flag collidable afin que les overlays ne créent pas de fausses collisions, ne consomment pas les régions libres et ne modifient pas la pagination.

La résolution des couches parcourt paresseusement les éléments actifs de chaque page physique ; la sélection par rôle n'alloue donc pas de liste temporaire de références.

Les streams Dataset redémarrables s'arrêtent à l'échantillon borné de colonne auto sans parcourir le reste. Les tables résolvent largeurs fixed, auto échantillonnées et flex pondérées ; paginent lignes fixes ou mesurées par callback avec capacité correcte du header initial/répété ; conservent limites de groupe et styles conditionnels ; et émettent les totaux integer/decimal/currency vérifiés uniquement sur la dernière page. Les limites de ligne, field, cellule, expression, échantillon et page échouent fermées.

Le YAML strict expose désormais ce contrat directement : un élément type: table doit déclarer ses colonnes et un binding vers un tableau. Groupement, totaux, styles conditionnels, répétition du header et taille des lignes restent typés dans TableIr ; chaque ligne liée doit être un object. Les limites de lignes, fields et cellules propres au template peuvent seulement réduire les limites globales de ressources du compilateur.

Le layout transforme maintenant chaque page de table bornée en ResolvedTableFragment immuable sur une page physique de la scène. Colonnes exactes, headers répétés, rectangles ligne/cellule, styles data, continuité de groupe, totaux et texte façonné sont fixés avant export. Les continuations respectent les bornes globales de pages et collision ; les exporters ne mesurent ni ne repaginent.

PDF éditable/flattened/hybride, SVG, PNG/JPEG et HTML sémantique/fixe rendent maintenant directement ces fragments résolus. L'usage des polices PDF inclut chaque run de cellule, SVG et HTML incluent les polices des styles data, et le raster trace les mêmes glyphes façonnés. Le preflight valide structure de table, bornes des cellules, diagnostics de texte et exigences de polices incorporées avant export.

Les sorties sont PDF éditable/flattened/hybride, SVG, PNG, JPEG, HTML sémantique/fixe, CSV streaming et masques PNG/PDF/SVG/JSON. Les modes préparés échouent explicitement ou figurent dans ExportLossReport.

Chaque format de document écrit vers un writer fourni par l'appelant et offre aussi des octets bornés en mémoire ; le CSV de dataset streame ses lignes par les deux mêmes interfaces. Le DPI ne concerne que PNG/JPEG et la qualité uniquement JPEG. PNG préserve la transparence, tandis que JPEG enregistre l'aplatissement alpha du style ou de l'image avant une sortie stricte. Le HTML fixe ne déclare pas la capacité sémantique. PDF émet des métadonnées déterministes de titre, creator et producer ; le PDF éditable embarque les subsets exacts de glyphes et les maps Unicode. PDF Hybrid peint des contours déterministes et ajoute un texte Unicode invisible et subsetté aux coordonnées résolues des glyphes pour la recherche, la sélection et l'extraction. Liens, bookmarks, accessibilité tagged, PDF/A, WebP, XLSX, ZPL et ESC/POS restent des contrats préparés explicites.

La validation possède des étapes explicites de schéma, données typées, layout résolu et preflight conscient de l'exporter. Les warnings bornés sont first-class ; strict les rejette et la troncature du rapport échoue fermée. Le preflight détecte les écarts binding, asset, glyphe, collision, overflow, DPI effectif, vector/CMYK/alpha JPEG, police incorporée pour PDF editable/hybride et accessibilité demandée.

Les fingerprints déterministes cadrent versions schéma et engine, template/données/patches canoniques, digests des assets référencés et des polices enregistrées. Les champs JSON canoniques utilisent une passe de dimensionnement suivie d'un hachage SHA-256 direct sous le budget agrégé max_output_bytes, en conservant le framing V1 sans retenir un buffer JSON complet. LayoutEngine::resolve_cached ne résout qu'en cas de miss du SceneCache borné, renvoie des scènes immuables partagées pour render-many et rejette les anciennes versions d'engine. Le batch ordonné complet de patches a une limite globale ; remove/replace rejettent tout subtree cible contenant un descendant locked.

Le travail sur entrée hostile possède des bornes explicites. Le binding partage un seul budget d'éléments entre racines, descendants et expansion des repeats, avec annulation/progression coopérative aux frontières d'élément. Le layout a un budget total de comparaisons spatiales en plus du reflow borné. Les lectures filesystem sous racine canonique rejettent traversal et liens sortants, ouvrent sans suivre un symlink/reparse point final substitué, appliquent la limite d'octets et revalident le sandbox autour de la lecture. L'annulation d'export précède toute sortie visible par l'appelant.

Les gates de fiabilité comprennent des snapshots exacts du SVG visuel et du masque de collision, des properties de géométrie fixed-point et des cibles fuzz séparées pour le pipeline YAML/bind/layout borné, l'Unicode arbitraire et les textes trop grands, les assets raster corrompus, tailles absurdes/overlaps/ anchors circulaires et graphes d'include malformés, circulaires ou trop profonds. Une entrée invalide peut échouer avec une erreur typée, mais ne doit jamais provoquer panic, boucle infinie ou allocation sans borne explicite.

Le debug reste une couche dérivée en lecture seule. DebugOverlay fournit des grilles bornées de 1/5/10/20 points, règles, coordonnées, IDs, bounds distincts, anchors, régions résolues, géométrie safe/collision, exclusions et crosshairs sans changer layout ni ordre de peinture. Les masques collision/layout/visual/combined dérivent leurs rectangles occupés et libres par vue et exportent PNG, PDF, SVG ou un JSON stable occupied/free/collisions/overflow. inspect et explain conservent une trace structurée des x/y/width/height source, anchors, région, mesure, policy de collision, page/reflow et provenance. Le JSON, le SVG et le PDF du masque comptent d'abord sous max_output_bytes sans retenir la sortie, rejettent un résultat excessif avant de toucher la destination, puis sérialisent directement dans le writer de l'appelant. PDF émet des objets indépendants, un stream de commandes fixed-point de taille exacte et son xref sans buffer de page ni de fichier complet. collision_mask_json_4m mesure une sortie exacte de 4 188 826 octets ; collision_mask_pdf_100k mesure 100 000 rectangles et un PDF exact de 1 800 626 octets avec checkpoints RSS idle, pic et retenu.

Le macrobenchmark a4_report_export_matrix mesure le pipeline A4 maintenu de deux pages comme une opération bornée : décodage YAML et données typées, patch runtime, mesure/layout/collision/reflow, preflight et neuf sorties streamées. Il couvre PDF éditable, flattened et hybride ; SVG ; HTML sémantique et fixe ; PNG ; JPEG avec pertes best-effort explicites ; et CSV du dataset. Trois échantillons isolés du commit propre sur Apple M1 ont mesuré 70,56 ms p50, 71,34 ms p95, 0,22 ms de MAD et 10,64 Mio de RSS de pic.

Le core déterministe ne dépend pas de l'IA. appcore-filemaker-ai est un bridge optionnel de 20 outils sur appcore-ai; appcore-filemaker-cli est l'adaptateur processus borné. Exemples et preuves se trouvent sur la branche Runtime beta.

Export et preflight rejettent indépendamment les scènes résolues publiques anciennes ou malformées et appliquent les budgets pages, éléments, paths, lignes, texte et coordonnées avant toute écriture. Overlay diagnostique, masque de collision/JSON et régions libres consomment aussi des limites explicites de comparaisons et géométrie conservée. Les ID validés préservent l'invariant du constructeur lors de la désérialisation. Les exports contrôlés observent l'annulation et signalent la progression depuis les vraies boucles d'éléments des renderers, avant d'écrire la sortie préparée à l'appelant. Le pipeline de polices explicites utilise harfrust, maintenu par le projet HarfBuzz, pour le shaping et skrifa, de Google Fonts, pour validation, métriques et outlines ; il ne découvre aucune police du système. Une police valide sans capital height OS/2 utilise ascent comme policy PDF CapHeight explicite et déterministe ; les advances absentes échouent.

Les exemples Rust exécutables conservent le document dans les fichiers séparés basic.yml et intermediate.yml. Les données typées restent dans des JSON correspondants séparés. Le lanceur de base produit un SVG complet d'une page avec texte lié, dessins sémantiques, sparkline et table stylée. L'intermédiaire produit un rapport confidentiel de deux pages exactes avec numérotation, filigrane répété, graphiques vectoriels, table paginée, preflight strict, PDF éditable, HTML fixe et aperçus SVG par page. Tous deux enregistrent explicitement la police Noto Sans sous OFL fournie, sans dépendre des polices hôte. Le code Rust n'intègre ni YAML ni JSON.

Documentation maintenue par le crate : guide, exemple de base et exemple intermédiaire.