///|
pub fn compile(
  source : String,
  target? : CompileTarget = Text,
  line_style? : @backend.LineStyle = @backend.LineStyle::Ascii,
  ansi? : Bool = false,
  disable_math? : Bool = false,
  paper? : @backend.Paper = @backend.Paper::A4,
  halfwidth_punct? : Bool = false,
) -> String raise @parsing.SyntaxError {
  let block = @parsing.document.parse(source |> @talc.Input::new)
  let blocks = match block {
    Ok(blocks) => blocks
    Err(e) => raise @parsing.SyntaxError::of_parse_error(e)
  }

  match target {
    Html =>
      @backend.render_document_page(
        blocks,
        paper~,
        target=@backend.Mathml,
        disable_math~,
        halfwidth_punct~,
      )
    HtmlText =>
      @backend.render_page(
        @backend.render_pre(
          @backend.render_terminal_document(
            blocks,
            line_style~,
            ansi=false,
            disable_math~,
            halfwidth_punct~,
          ),
        ),
        paper~,
      )
    Text =>
      @backend.render_terminal_document(
        blocks,
        line_style~,
        ansi~,
        disable_math~,
        halfwidth_punct~,
      )
  }
}

///|
/// Compiles `source` with the cmark parser and renders it as terminal text.
///
/// Unlike [`compile`](`compile`), parsing is delegated to the CommonMark-
/// conformant `@cmark` port, so this entry can never fail.
pub fn compile_cmark(
  source : String,
  options : @cmark.Options,
  line_style? : @backend.LineStyle = @backend.LineStyle::Ascii,
  ansi? : Bool = false,
  disable_math? : Bool = false,
  halfwidth_punct? : Bool = false,
) -> String {
  @backend.render_terminal_events(
    @cmark.parse(source, options),
    line_style~,
    ansi~,
    disable_math~,
    halfwidth_punct~,
  )
}

///|
pub(all) enum CompileTarget {
  Text
  Html
  HtmlText
}