// SPDX-License-Identifier: CC-BY-SA-4.0
// (PMPL-1.0-or-later preferred; MPL-2.0 required for Hex.pm)
// Copyright (c) 2026 Jonathan D.A. Jewell (hyperpolymath) <j.d.a.jewell@open.ac.uk>

= a2ml_gleam
:author: Jonathan D.A. Jewell
:toc: preamble
:icons: font

== Overview

A2ML parser and renderer for https://gleam.run[Gleam]. Parses
https://github.com/hyperpolymath/standards/tree/main/a2ml[A2ML (Attested Markup Language)]
source text into a typed Gleam AST and renders it back to A2ML surface syntax with
round-trip fidelity.

A2ML is a lightweight markup format designed for AI-generated content with provenance
tracking through attestation chains and trust levels.

== Installation

[source,sh]
----
gleam add a2ml_gleam
----

Or add manually to `gleam.toml`:

[source,toml]
----
[dependencies]
a2ml_gleam = ">= 0.1.0 and < 1.0.0"
----

Package: https://hex.pm/packages/a2ml_gleam[hex.pm/packages/a2ml_gleam]

== Usage

[source,gleam]
----
import a2ml_gleam
import a2ml_gleam/parser
import a2ml_gleam/renderer

pub fn main() {
  let input = "# My Document\n\n@version 1.0\n\nHello, A2ML!"
  let assert Ok(doc) = a2ml_gleam.parse(input)
  let output = a2ml_gleam.render(doc)
}
----

=== Working with the AST

[source,gleam]
----
import a2ml_gleam/parser
import a2ml_gleam/types.{
  Document, Heading, Paragraph, Text, Strong,
  Directive, Attestation, TrustLevel, Verified,
}

pub fn inspect_document(input: String) {
  let assert Ok(doc) = parser.parse(input)

  // Access the document title
  case doc.title {
    Ok(title) -> io.println("Title: " <> title)
    Error(Nil) -> io.println("No title")
  }

  // Iterate over blocks
  list.each(doc.blocks, fn(block) {
    case block {
      Heading(level, content) -> // ...
      Paragraph(content) -> // ...
      DirectiveBlock(directive) -> // ...
      AttestationBlock(attestation) -> // ...
      _ -> Nil
    }
  })
}
----

== API Overview

=== Top-Level Functions

[cols="2,3"]
|===
| Function | Description

| `a2ml_gleam.parse(input)`
| Parse an A2ML string into a `Result(Document, ParseError)`

| `a2ml_gleam.render(doc)`
| Render a `Document` back to A2ML text
|===

=== Modules

[cols="2,3"]
|===
| Module | Contents

| `a2ml_gleam/types`
| Core data types: `Document`, `Block`, `Inline`, `Directive`, `Attestation`, `TrustLevel`, `Manifest`

| `a2ml_gleam/parser`
| `parse(String) -> Result(Document, ParseError)`

| `a2ml_gleam/renderer`
| `render(Document) -> String`
|===

=== Core Types

`Document`:: Top-level container with `title`, `directives`, `blocks`, and `attestations` fields.

`Block`:: Sum type with variants: `Heading`, `Paragraph`, `CodeBlock`, `DirectiveBlock`, `AttestationBlock`, `ThematicBreak`, `BlockQuote`, `ListBlock`.

`Inline`:: Sum type with variants: `Text`, `Emphasis`, `Strong`, `Code`, `Link`.

`Directive`:: Machine-readable metadata with `name`, `value`, and `attributes` fields.

`Attestation`:: Provenance record with `identity`, `role`, `trust_level`, `timestamp`, and `note`.

`TrustLevel`:: Ordered trust scale: `Unverified` < `Automated` < `Reviewed` < `Verified`.

`Manifest`:: High-level view extracted from a `Document`, collecting directives and attestations.

== Requirements

* Gleam >= 1.0
* gleam_stdlib >= 0.44.0

== Licensing

SPDX-License-Identifier: MPL-2.0

PMPL-1.0-or-later is preferred. MPL-2.0 is used as a fallback because Hex.pm requires an
OSI-approved license identifier. See link:LICENSE[LICENSE] for the full text.

== Part of the A2ML Ecosystem

This binding is part of the link:../../README.adoc[A2ML specification and tooling] in the
https://github.com/hyperpolymath/standards[standards monorepo]. See the
link:../README.adoc[bindings overview] for all available language bindings.
