{"_id":"@axiome-apps/atelier-prose","_rev":"2-5784452976003b7be501e1c599663e87","name":"@axiome-apps/atelier-prose","dist-tags":{"latest":"0.1.1"},"versions":{"0.1.0":{"name":"@axiome-apps/atelier-prose","version":"0.1.0","keywords":["markdown","directives","prose","rich-text","cms","echoppe","prisme"],"author":{"name":"MrCasquette"},"license":"CECILL-2.1","_id":"@axiome-apps/atelier-prose@0.1.0","maintainers":[{"name":"mrcasquette","email":"contact@vincent-cottalorda.fr"}],"dist":{"shasum":"187ae289f92377bbca66a7b12d6d2c40bf3a7d57","tarball":"https://registry.npmjs.org/@axiome-apps/atelier-prose/-/atelier-prose-0.1.0.tgz","fileCount":23,"integrity":"sha512-61tqgXl2hJzle/UlJYVrN27yd8E1wtka/SMmXWUPNnd27yO1SZa2d5JsCFyaL8/282224YPsHD+lRIFKISrb2w==","signatures":[{"sig":"MEYCIQD0JloFtHgwK4O8sy27ruL3VvTvuF079XDqsRX8fSbv8QIhAL3+jHF9+EgpISBnm3ex47j6XJPfGiIUiy7+0hgJDhnC","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":49798},"main":"./dist/index.js","type":"module","types":"./dist/index.d.ts","module":"./dist/index.js","exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js"}},"gitHead":"fe5f4722ea2d0c0713b6df25e64bcb83774849f6","scripts":{"test":"bun test src","build":"tsc -p tsconfig.build.json","type-check":"tsc --noEmit"},"_npmUser":{"name":"mrcasquette","email":"contact@vincent-cottalorda.fr"},"_npmVersion":"11.16.0","description":"Markdown à directives — du texte en entrée, un arbre en sortie. Le noyau de directives, sa validation et un rendu HTML générique. Partagé par Échoppe et Prisme.","directories":{},"sideEffects":false,"_nodeVersion":"24.18.0","dependencies":{"mdast-util-directive":"^3.1.0","mdast-util-from-markdown":"^2.0.3","micromark-extension-directive":"^4.0.0"},"publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"bun-types":"^1.3.14","typescript":"6.0.3","@types/mdast":"^4.0.4"},"_npmOperationalInternal":{"tmp":"tmp/atelier-prose_0.1.0_1787571687964_0.40078473600627396","host":"s3://npm-registry-packages-npm-production"}},"0.1.1":{"name":"@axiome-apps/atelier-prose","version":"0.1.1","description":"Markdown à directives — du texte en entrée, un arbre en sortie. Le noyau de directives, sa validation et un rendu HTML générique. Partagé par Échoppe et Prisme.","repository":{"type":"git","url":"git+https://github.com/MrCasquette/atelier.git","directory":"packages/prose"},"type":"module","main":"./dist/index.js","module":"./dist/index.js","types":"./dist/index.d.ts","exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js"}},"sideEffects":false,"publishConfig":{"access":"public"},"scripts":{"build":"tsc -p tsconfig.build.json","test":"bun test src","type-check":"tsc --noEmit"},"keywords":["markdown","directives","prose","rich-text","cms","echoppe","prisme"],"author":{"name":"MrCasquette"},"license":"CECILL-2.1","dependencies":{"mdast-util-directive":"^3.1.0","mdast-util-from-markdown":"^2.0.3","micromark-extension-directive":"^4.0.0"},"devDependencies":{"@types/mdast":"^4.0.4","bun-types":"^1.3.14","typescript":"6.0.3"},"gitHead":"4cb8ce3ffacf0612e1d15e447dd65451bafdfebd","_id":"@axiome-apps/atelier-prose@0.1.1","bugs":{"url":"https://github.com/MrCasquette/atelier/issues"},"homepage":"https://github.com/MrCasquette/atelier#readme","_nodeVersion":"24.20.0","_npmVersion":"11.19.1","dist":{"integrity":"sha512-t5SZtZtuL9pVkDbQOErw1KHSvLmeuOU5KdV00vs4tjUpnPyAH1NzuWGKPauRwqAk3RHbQw0M6xD9IZIuaZJ9ow==","shasum":"7db553aaec5c481896b519b55201e7171b6e2bb4","tarball":"https://registry.npmjs.org/@axiome-apps/atelier-prose/-/atelier-prose-0.1.1.tgz","fileCount":23,"unpackedSize":49935,"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/@axiome-apps%2fatelier-prose@0.1.1","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEYCIQDNfkar9+vZieqjfi3w3wfpZDEsJb2GVhWHfnUDdIblDwIhAMETR0anBr6F74Op9mtzV9XR+NRpqFsplqLuzXmL10pZ"}]},"_npmUser":{"name":"GitHub Actions","email":"npm-oidc-no-reply@github.com","trustedPublisher":{"id":"github","oidcConfigId":"oidc:e2b59356-eb20-4bea-b99e-80c0582ea5cb"}},"directories":{},"maintainers":[{"name":"mrcasquette","email":"contact@vincent-cottalorda.fr"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/atelier-prose_0.1.1_1789058320435_0.8909396225082284"},"_hasShrinkwrap":false}},"time":{"created":"2026-08-24T11:41:27.666Z","modified":"2026-09-10T16:38:40.951Z","0.1.0":"2026-08-24T11:41:28.094Z","0.1.1":"2026-09-10T16:38:40.577Z"},"author":{"name":"MrCasquette"},"license":"CECILL-2.1","keywords":["markdown","directives","prose","rich-text","cms","echoppe","prisme"],"description":"Markdown à directives — du texte en entrée, un arbre en sortie. Le noyau de directives, sa validation et un rendu HTML générique. Partagé par Échoppe et Prisme.","maintainers":[{"name":"mrcasquette","email":"contact@vincent-cottalorda.fr"}],"readme":"# `@axiome-apps/atelier-prose` — du texte en entrée, un arbre en sortie\n\nCe que le paquet livre : **la traduction d'un texte Markdown à directives en un arbre exploitable**,\net rien d'autre. Il ne rend pas, il ne stocke pas, il n'interroge personne (ADR-0061).\n\n```bash\nbun add @axiome-apps/atelier-prose\n```\n\n```ts\nimport { parseProse, proseIssues, proseToHtml } from '@axiome-apps/atelier-prose';\n\nconst tree = parseProse(source); // le contrat\nproseToHtml(tree); // la commodité\nproseIssues(tree); // ce qui ne va pas, sans rien refuser\n```\n\n## Aucune dépendance interne\n\nNi `@repo/db`, ni `@repo/fields`, ni `@repo/shared`. C'est le paquet le plus pur du dépôt, et ce\nn'est pas une coquetterie : un registre de prose se valide **sans base**, et un arbre se teste sans\nDOM. Le modèle des champs a d'ailleurs été écarté volontairement — sur ses douze `kind`, une\ndirective en emploierait trois, et de travers : `list`, `repeater` et `component` n'ont aucun sens\ndans une chaîne de caractères, et un attribut de directive est **toujours** une `string`.\n\n## Les deux invariants, et ce qui les tient\n\n**Le HTML brut est refusé à la source.** `htmlFlow` et `htmlText` sont désactivés dans le tokenizer,\nsi bien qu'un `<script>` écrit dans le contenu ressort en **texte** et sera échappé au rendu. Ce\nn'est pas une consigne : c'est l'entrée qui rend la sortie close, et sans elle tout le raisonnement\nde sécurité s'effondre. Deux tests en font foi.\n\n**L'arbre est éphémère.** La base ne contient que le texte source, octet pour octet celui qui a été\nécrit ; l'arbre est reconstruit à chaque rendu. Le mettre en cache en base ramènerait à un format\npropriétaire avec deux sources de vérité — c'est la seule dérive qui détruirait la thèse de l'ADR\n**sans qu'aucun test ne tombe**.\n\n## Frontière\n\n| Ici | Ailleurs |\n|---|---|\n| Le texte devient un arbre | Le stockage du texte, qui est un champ comme un autre |\n| Ce qu'est une directive, ses trois formes | Le noyau de directives et ce que chacune produit |\n| Le parcours de l'arbre | Le rendu — chez le consommateur, jamais dans le framework |\n\n`mdast` s'arrête à `parse.ts` : au-delà, seul l'arbre de `tree.ts` circule. C'est ce qui rend l'outil\nde parsing remplaçable — s'il est abandonné, on en réécrit un et **aucune donnée ne bouge**.\n\n## Le noyau, et pourquoi il n'a que des enveloppes\n\nSept directives que nos thèmes s'engagent à dessiner : `warning`, `note`, `tip`, `figure`, `quote`,\n`cta`, `highlight`. **Aucune n'est un `leaf`**, et c'est la contrainte qui garde le sérialiseur HTML\npurement générique — sans table de structures par directive.\n\nLe critère qui la tient :\n\n> **Si Markdown sait produire le contenu, on enveloppe. Sinon, c'est un `leaf`.**\n\nUne image, un lien, du texte : Markdown les produit. Une vidéo intégrée, une iframe : non — ce sera\nun `leaf`, il exigera que le rendu connaisse sa structure, et ce sera pour plus tard.\n\nTout le reste traverse **sans validation ni garantie de style**. On ne valide que ce qu'on garantit :\nune V1 qui refuserait les directives du dev offrirait moins que le HTML, et le choix de Markdown ne\nse défendrait plus.\n\n## Deux sorties, et laquelle est le contrat\n\n`proseToHtml` est une **commodité** : elle rend tout le noyau et porte la prévisualisation de\nl'administration. Mais une directive du dev qui doit produire de la **structure** — un média, une\niframe — passe par l'arbre, puisqu'on ne fabrique pas un `<img>` en CSS.\n\nLe rendu par le HTML impose aussi `v-html` / `set:html`, sort les liens internes du routeur et perd\nl'optimisation d'images. **L'arbre est donc le contrat**, le HTML le raccourci.\n\n## La sécurité tient à trois choses, toutes testées\n\n1. **Le HTML brut est refusé à l'entrée** — un `<script>` ressort en texte.\n2. **Les URL sont filtrées** — désactiver le HTML n'arrête pas `[clic](javascript:alert(1))`. Seuls\n   `http`, `https`, `mailto`, `tel` et le relatif passent ; la casse et les caractères de contrôle ne\n   masquent pas un schéma. Une URL refusée fait perdre son `href` au lien, qui reste **inerte et\n   visible** plutôt que redirigé ailleurs.\n3. **Les noms d'attributs sont filtrés** — ils viennent du texte, donc de n'importe où, et le préfixe\n   `data-` n'y suffirait pas : c'est le nom lui-même qui doit être inerte.\n\n## Les trois formes d'une directive\n\n```md\n:::warning        un corps de prose        → enveloppe\nRetours sous 14 jours.\n:::\n\n::figure[Légende]{src=…}                   → média, un label et des attributs\n\nUn mot :highlight[mis en avant].           → inline, au fil de la phrase\n```\n\nUne directive **crée** un nœud, elle n'en décore pas un qui existe. Pour qu'un lien ait l'allure d'un\nbouton, on l'enveloppe — et le lien reste un vrai lien Markdown, cliquable partout :\n\n```md\n:::cta\n[Nous contacter](/contact)\n:::\n```\n","readmeFilename":"README.md","homepage":"https://github.com/MrCasquette/atelier#readme","repository":{"type":"git","url":"git+https://github.com/MrCasquette/atelier.git","directory":"packages/prose"},"bugs":{"url":"https://github.com/MrCasquette/atelier/issues"}}