use(require(“atomy”))

require(“atomy/codeloader”)

data = require(“anatomy/data”) meta = require(“anatomy/stages/meta”) traverse = require(“anatomy/stages/traverse”) collect = require(“anatomy/stages/collect”)

hl = require(“hl”)

def(template(mod)):

data MetaBlock new(
  [part]:
    part template = mod)

def(set-title(content, tag-name = data sanitize(content), *extra-tag-names)):

data MetaBlock new(
  [part]:
    part title = content

    part tag = part set-tag(tag-name, .self, content)

    extra-tag-names each [t]:
      part set-tag(t))

def(title(content, tag-name = data sanitize(content), *extra-tag-names)):

[ set-title(content, tag-name, *extra-tag-names)

  data ResolveBlock new(
    [part]:
      data Block new(
        [ data Target new(part tag name)
          content
        ]
        .header(part page-depth + 1)))
]

def(inline-sections):

data MetaBlock new(
  [part]:
    part style properties << .inline-sections)

def(split-sections):

data MetaBlock new(
  [part]:
    part style properties << .split-sections)

def(table-of-contents):

data MetaBlock new(
  [part]:
    part style properties << .split-sections
    part style properties << .toc)

def(mobile-optimized):

data MetaBlock new(
  [part]:
    part mobile-optimized? = true)

def(omit-children-from-table-of-contents):

data MetaBlock new(
  [part]:
    part omit-children-from-table-of-contents? = true)

def(section(title, *tag-names, content)):

decode(title(title, *tag-names), content)

def(include-section(path)):

Atomy CodeLoader load(path) doc

def(include-sections(path)):

Dir glob(path) collect [s]:
  Atomy CodeLoader load(s) doc

def(target-element(tag-name, display = nil)):

data CollectElement new(
  [part]:
    part set-tag(tag-name, .anchor(tag-name), display)
    data Target new(tag-name))

def(verbatim(content)):

data Block new(content, .verbatim)

def(hyperlink(url, content)):

data Element new(content, .hyperlink(url))

def(reference(tag-name, content = nil)):

data ResolveElement new(
  [part]:
    tag = part find-tag(tag-name)
    unless(tag):
      warning(.undefined(tag-name))

    data Reference new(
      tag
      content || ((tag && tag display) || tag-name)))

def(centered(content)):

data Block new(content, .centered)

def(image(asset-path, alt-text = “”)):

data ResolveElement new(
  [part]:
    part assets << File expand-path(asset-path)

    data Element new(
      alt-text
      .image(File basename(asset-path))))

def(definitions(content)):

defs = []
Array(content) select [x]:
  x match:
    .item(name, val):
      defs << [name, val]

data Itemization new(defs)

def(item(name, content)): .item(name, content)

def(italic(content)): data Element new(content, .italic)

def(strike(content)): data Element new(content, .strike)

def(list(*elements)): data List new(elements)

def(ordered-list(*elements)): data OrderedList new(elements)

def(bold(content)): data Element new(content, .bold)

def(smaller(content)): data Element new(content, .smaller)

def(larger(content)): data Element new(content, .larger)

def(superscript(content)): data Element new(content, .superscript)

def(subscript(content)): data Element new(content, .subscript)

def(code(content)): data Element new(content, .tt)

def(margin-note(content)): data Block new(content, .margin-note)

def(aux(content)): data Element new(content, .aux)

def(inset(content)): data Block new(content, .inset)

fn(format-inline(tokens, link-only = nil)):

tokens collect [t]:
  data Element new(
    -- constants, identifiers, and operators
    if((link-only && link-only include?(t contents)) ||
        (!link-only && ["no", "n", "o"] include?(t type tag)))
      then:
        data ResolveElement new(
          [part]:
            tag = part find-tag(t contents)
            if(tag)
              then: data Reference new(tag, t contents)
              else: t contents)
      else: t contents
    .class(t type tag))

fn(format-block(tokens, link-only = nil)):

data Block new(
  verbatim(format-inline(tokens, link-only))
  .class("highlight"))

fn(collect-content(s & String)): s fn(collect-content(ss & Array)): ss collect [s]: collect-content(s); join

def(codeblock(language, content)):

format-block(hl load(language) new(collect-content(content)) run) rescue:
  LoadError:
    warning(.unknown-language(language))
    verbatim(content)

def(newline): data Element new(“”, .newline)

def(no-break(content)): data Element new(content, .no-break)

def(decode(*cs)):

part = data Part new

meta over(cs, part)

part