|
| 1 | +[](https://github.com/sponsors/hyperpolymath) |
| 2 | + |
| 3 | += a2ml_ex |
| 4 | +:toc: preamble |
| 5 | +:icons: font |
| 6 | + |
| 7 | +image:https://img.shields.io/badge/OpenSSF-Best_Practices-green?logo=opensourcesecurity[OpenSSF Best Practices, link="https://www.bestpractices.dev/en/projects/new?repo_url=https://github.com/hyperpolymath/a2ml_ex"] |
| 8 | + |
| 9 | +== Overview |
| 10 | + |
| 11 | +**Elixir implementation of A2ML (Attested Markup Language) parser and renderer.** |
| 12 | + |
| 13 | +A2ML is a structured markup language with built-in attestation provenance, directive metadata, and trust-level tracking. This library provides a complete parser and renderer for A2ML documents in pure Elixir. |
| 14 | + |
| 15 | +== Features |
| 16 | + |
| 17 | +* Parse A2ML documents from strings or files |
| 18 | +* Render AST back to A2ML surface syntax (round-trip support) |
| 19 | +* Typed AST with structs for blocks, inlines, directives, and attestations |
| 20 | +* Trust-level hierarchy: `:unverified`, `:automated`, `:reviewed`, `:verified` |
| 21 | +* Directive blocks with key-value attributes |
| 22 | +* Attestation provenance chain |
| 23 | +* Zero dependencies beyond Elixir standard library |
| 24 | + |
| 25 | +== Quick Start |
| 26 | + |
| 27 | +Add to your `mix.exs`: |
| 28 | + |
| 29 | +[source,elixir] |
| 30 | +---- |
| 31 | +defp deps do |
| 32 | + [{:a2ml_ex, git: "https://github.com/hyperpolymath/a2ml_ex.git"}] |
| 33 | +end |
| 34 | +---- |
| 35 | + |
| 36 | +Then run: |
| 37 | + |
| 38 | +[source,bash] |
| 39 | +---- |
| 40 | +mix deps.get |
| 41 | +mix compile |
| 42 | +---- |
| 43 | + |
| 44 | +== Usage |
| 45 | + |
| 46 | +[source,elixir] |
| 47 | +---- |
| 48 | +# Parse A2ML document |
| 49 | +{:ok, document} = A2ML.parse("# Hello World\n\nSome **bold** text.") |
| 50 | + |
| 51 | +# Render back to A2ML |
| 52 | +{:ok, rendered} = A2ML.render(document) |
| 53 | + |
| 54 | +# Handle parse errors |
| 55 | +{:error, %A2ML.ParseError{}} = A2ML.parse("invalid syntax") |
| 56 | +---- |
| 57 | + |
| 58 | +== Module Structure |
| 59 | + |
| 60 | +[cols="1,3"] |
| 61 | +|=== |
| 62 | +| Module | Purpose |
| 63 | + |
| 64 | +| `A2ML` |
| 65 | +| Main module - re-exports public API |
| 66 | + |
| 67 | +| `A2ML.Document` |
| 68 | +| Document struct and functions |
| 69 | + |
| 70 | +| `A2ML.Block` |
| 71 | +| Block-level elements (headings, paragraphs, lists, etc.) |
| 72 | + |
| 73 | +| `A2ML.Inline` |
| 74 | +| Inline elements (bold, italic, code, links, etc.) |
| 75 | + |
| 76 | +| `A2ML.Directive` |
| 77 | +| Directive blocks with attributes |
| 78 | + |
| 79 | +| `A2ML.Attestation` |
| 80 | +| Attestation provenance and trust levels |
| 81 | + |
| 82 | +| `A2ML.Parser` |
| 83 | +| Parser implementation (string to AST) |
| 84 | + |
| 85 | +| `A2ML.Renderer` |
| 86 | +| Renderer implementation (AST to string) |
| 87 | + |
| 88 | +| `A2ML.Error` |
| 89 | +| Error types and handling |
| 90 | +|=== |
| 91 | + |
| 92 | +== A2ML Syntax Reference |
| 93 | + |
| 94 | +[source] |
| 95 | +---- |
| 96 | +# Heading |
| 97 | + |
| 98 | +Paragraph with **bold**, *italic*, `code`, [link](url), and @ref(id). |
| 99 | + |
| 100 | +@directive-name(key=val): single line value |
| 101 | + |
| 102 | +@multi-line: |
| 103 | +Content spanning |
| 104 | +multiple lines |
| 105 | +@end |
| 106 | + |
| 107 | +!attest |
| 108 | +identity: Jonathan D.A. Jewell |
| 109 | +role: author |
| 110 | +trust-level: verified |
| 111 | +timestamp: 2026-03-16T00:00:00Z |
| 112 | +!end |
| 113 | + |
| 114 | +- Bullet list item |
| 115 | +- Another item |
| 116 | + |
| 117 | +> Block quote text |
| 118 | +
|
| 119 | +```elixir |
| 120 | +defmodule Example do |
| 121 | + def hello, do: "world" |
| 122 | +end |
| 123 | +``` |
| 124 | +---- |
| 125 | + |
| 126 | +== Development |
| 127 | + |
| 128 | +[source,bash] |
| 129 | +---- |
| 130 | +mix deps.get # Install dependencies |
| 131 | +mix compile # Compile project |
| 132 | +mix test # Run tests |
| 133 | +mix format # Format code |
| 134 | +mix creds check # Check credentials |
| 135 | +---- |
| 136 | + |
| 137 | +== Configuration |
| 138 | + |
| 139 | +Add to `config/config.exs`: |
| 140 | + |
| 141 | +[source,elixir] |
| 142 | +---- |
| 143 | +config :a2ml_ex, |
| 144 | + default_trust_level: :reviewed, |
| 145 | + strict_mode: true |
| 146 | +---- |
| 147 | + |
| 148 | +== Related Libraries |
| 149 | + |
| 150 | +* link:https://github.com/hyperpolymath/a2ml-deno[a2ml-deno] — Deno/ReScript implementation |
| 151 | +* link:https://github.com/hyperpolymath/a2ml-rs[a2ml-rs] — Rust implementation |
| 152 | +* link:https://github.com/hyperpolymath/a2ml-haskell[a2ml-haskell] — Haskell implementation |
| 153 | +* link:https://github.com/hyperpolymath/a2ml_gleam[a2ml_gleam] — Gleam implementation |
| 154 | +* link:https://github.com/hyperpolymath/tree-sitter-a2ml[tree-sitter-a2ml] — Tree-sitter grammar |
| 155 | +* link:https://github.com/hyperpolymath/vscode-a2ml[vscode-a2ml] — VS Code extension |
| 156 | + |
| 157 | +== Trust Levels |
| 158 | + |
| 159 | +A2ML supports four trust levels in a hierarchy: |
| 160 | + |
| 161 | +[cols="1,3"] |
| 162 | +|=== |
| 163 | +| Level | Meaning |
| 164 | + |
| 165 | +| `:unverified` |
| 166 | +| Content has not been reviewed or attested |
| 167 | + |
| 168 | +| `:automated` |
| 169 | +| Content generated or verified by automated systems |
| 170 | + |
| 171 | +| `:reviewed` |
| 172 | +| Content reviewed by human but not formally verified |
| 173 | + |
| 174 | +| `:verified` |
| 175 | +| Content formally verified with cryptographic attestation |
| 176 | +|=== |
| 177 | + |
| 178 | +== Directives |
| 179 | + |
| 180 | +Directives provide metadata and processing instructions: |
| 181 | + |
| 182 | +[source] |
| 183 | +---- |
| 184 | +@page-break |
| 185 | + |
| 186 | +@toc(depth=3): Table of Contents |
| 187 | + |
| 188 | +@include(file="chapter1.a2ml"): |
| 189 | + |
| 190 | +@template(name="article"): |
| 191 | +# {title} |
| 192 | +By {author} |
| 193 | + |
| 194 | +{content} |
| 195 | +@end |
| 196 | +---- |
| 197 | + |
| 198 | +== Attestations |
| 199 | + |
| 200 | +Attestations provide cryptographic provenance: |
| 201 | + |
| 202 | +[source] |
| 203 | +---- |
| 204 | +!attest |
| 205 | +identity: Alice Smith |
| 206 | +role: Editor |
| 207 | +trust-level: verified |
| 208 | +timestamp: 2026-03-16T12:00:00Z |
| 209 | +signature: 0xabc123... |
| 210 | +!end |
| 211 | +---- |
| 212 | + |
| 213 | +== Performance |
| 214 | + |
| 215 | +The Elixir implementation is optimized for: |
| 216 | + |
| 217 | +* Fast parsing of large documents |
| 218 | +* Memory-efficient AST representation |
| 219 | +* Concurrent rendering capabilities |
| 220 | +* Stream processing support |
| 221 | + |
| 222 | +== License |
| 223 | + |
| 224 | +SPDX-License-Identifier: MPL-2.0 |
| 225 | + |
| 226 | +Copyright (c) 2026 Jonathan D.A. Jewell (hyperpolymath) |
| 227 | + |
| 228 | +See link:LICENSE[LICENSE] for full license text. |
| 229 | + |
| 230 | +== Contributing |
| 231 | + |
| 232 | +See link:CONTRIBUTING.adoc[CONTRIBUTING.adoc] for contribution guidelines. |
| 233 | + |
| 234 | +== Roadmap |
| 235 | + |
| 236 | +See link:ROADMAP.adoc[ROADMAP.adoc] for planned features and enhancements. |
0 commit comments