Skip to content

Latest commit

 

History

History
366 lines (301 loc) · 13.6 KB

File metadata and controls

366 lines (301 loc) · 13.6 KB

This specification defines 3a-related concepts, terminology, and how 3a text files should be read.

Content:

Text

The 3a format is Unicode-based; all text-related terms below are interpreted in the context of Unicode.

Definitions:

  • "character"/"char" — a Unicode code point.
  • "space" / "ASCII space" — the U+0020 code point: .
  • "newline"U+000A (aka \n).
  • "word" — a sequence of characters delimited by text start/end, newline, or any whitespace character.
  • "line" — a sequence of characters delimited by text start/end or newline.
  • blank / void / empty line — a line of zero length.

The following characters MUST be ignored by a 3a decoder/encoder:

  • U+000D (aka \r)
  • C0 / C1 control characters: U+0000..U+001F, U+007F..U+009F except newline
  • Zero-width / joiner characters: U+200B–U+200F, U+FEFF, U+FE00–U+FE0F
  • Combining marks: U+0300..U+036F
  • Bidirectional control codes: U+202A..U+202E, U+2066..U+2069
  • Surrogate code points: U+D800..U+DFFF

The following characters MUST be replaced with ASCII space:

  • U+0009 (aka \t, tab)
  • any character from the Unicode "Space Separator" category
  • U+180E (Mongolian Vowel Separator)

Concepts

3a art is a collection of channels.

  • Channels are parallel sequences of frames indexed from 0.
  • Frames are sequences of rows.
  • Rows are sequences of elements of a type that is unique to each channel.

Two primary channels:

  • text — holds frames of textual art. Its elements are Unicode grapheme clusters.
  • colors — holds colors information (foreground, background) for text-channel elements. Its elements are names of color mappings.

Color mappings bind single-character names to color pairs.

Color pair consists of fg (foreground aka text color) and bg (background) colors. Each one may be:

  • ANSI 4-bit colors (Black/Red/Green/Yellow/Blue/Magenta/Cyan/White plus brightness)
  • ANSI 256-color codes
  • True 24-bit RGB colors
  • No color aka default color - depends on environment / software but typically white for fg and black for bg

Predefined color names:

  • _ — default color for both fg and bg.
  • 0 — ANSI 4-bit black fg (code 30), default bg.
  • 1 — ANSI 4-bit red fg (code 31), default bg.
  • 2 — ANSI 4-bit green fg (code 32), default bg.
  • 3 — ANSI 4-bit yellow fg (code 33), default bg.
  • 4 — ANSI 4-bit blue fg (code 34), default bg.
  • 5 — ANSI 4-bit magenta fg (code 35), default bg.
  • 6 — ANSI 4-bit cyan fg (code 36), default bg.
  • 7 — ANSI 4-bit white fg (code 37), default bg.
  • 8 — ANSI 4-bit bright black (gray) fg (code 90), default bg.
  • 9 — ANSI 4-bit bright red fg (code 91), default bg.
  • a — ANSI 4-bit bright green fg (code 92), default bg.
  • b — ANSI 4-bit bright yellow fg (code 93), default bg.
  • c — ANSI 4-bit bright blue fg (code 94), default bg.
  • d — ANSI 4-bit bright magenta fg (code 95), default bg.
  • e — ANSI 4-bit bright cyan fg (code 96), default bg.
  • f — ANSI 4-bit bright white fg (code 97), default bg.

Colors may be completely disabled; in that case the entire art should be shown using the environment's default fg/bg colors.

If all frames in a channel have identical content, that channel may use a single pinned frame (a frame that applies to all positions). Except when pinned frames are used, text and colors channels MUST have the same number of frames, forming a one-to-one mapping between them.

To control animation timing, there is a delay value that describes the pause between frames in milliseconds. Typically a single global delay is used for the whole art, but frame-specific delays may be specified. A frame-specific delay is applied after the frame is shown. The default global delay is 50 milliseconds.

3a art may also contain metadata such as title, authors, tags, etc.

File Format

Comments

Some parts of a 3a file are explicitly defined as supporting comments. When comments are supported, a comment is an entire line that starts with ;;. There are no block comments and no inline comments; a comment always occupies the whole line.

Structure

A 3a file consists of blocks separated by one or more blank lines. A file must contain at least a header block.

Each block starts with a block title line prefixed with @.

Block titles (after @ prefix) may contain only ASCII alphanumeric characters and the characters +, -, _, and ..
Block's title is a block's name in lowercase unless otherwise noted.

Header Block

The header is always the first block and contains art metadata. The header must be always presented even if void. The header supports comments.

Header's title is @3a.

The header is made of key-value pairs, one per line. In a key-value pair, the first word at the start of the line is the key; the remainder of the line is the value. Parsing of the value(s) is key-specific.

Some keys may appear multiple times as explicitly allowed; for other keys, multiple occurrences are an error. Keys and values are case-sensitive unless otherwise noted.

Title Key

title sets the art title. The whole line after the key is a single string value. Consecutive spaces SHOULD be collapsed to a single space during decoding/encoding. Leading and trailing spaces SHOULD be trimmed.

Author Key

author sets an author. Parsing rules are the same as for title. The author key may occur multiple times to indicate multiple authors. Multiple occurrences of author key with identical values (after trimming) MUST be deduplicated.

Original Author Key

orig-author sets the original author (for derivatives). Parsing rules are the same as for author.

Source Key

src sets a link to the art's original location (typically a URL). The whole line after the key is a single string; leading and trailing spaces SHOULD be trimmed.

Editor Key

editor provides information about the editor software used to create the art.

License Key

license defines an SPDX license expression (see https://spdx.org/licenses/) or the literal string proprietary. Leading and trailing spaces SHOULD be ignored. If the license key is not present, or the identifier is unknown, the license MUST be treated as proprietary unless a different rule applies in the context where the 3a file is stored (for example, an explicit LICENSE file in a repository).

Delay Key

delay defines frame delay(s) as described above. The value may contain a single global delay and/or multiple values separated by spaces.

  • Exactly one value MUST be the global delay: a string representation of an unsigned decimal integer (milliseconds).
  • Optionally, any number of frame-specific delays may be provided as colon-separated integer pairs: <frame>:<delay>. In each pair, the first integer is a frame number (starting from 0) and the second is a delay in milliseconds specific to that frame. Frame-specific delays for non-existent frames SHOULD be ignored.

If delay is not provided, the global delay defaults to 50 milliseconds and there are no frame-specific delays.

Loop Key

loop controls whether playback loops or stops after the first run. It has a single case-insensitive boolean value: yes (true) or no (false). If loop is not provided, looping is enabled by default.

Preview Key

preview sets the frame number to use as a preview. It accepts a single decimal integer value. The default is 0. If the specified frame does not exist, the preview key SHOULD be ignored.

Color Key

col defines a new color mapping. It has one or three values separated by spaces. First value is a single-character name. Next values can be:

  • fg:<color>
  • bg:<color>

Colors in fg:<color> and bg:<color> can be:

  • kebab-case ANSI color names (green, bright-red, etc.)
  • ANSI 3-bit or 8-bit color decimal codes (16, 196, etc.)
  • case-insensitive RGB hex color codes (e.g. ff00A0)

There can be only one fg and one bg color in mapping.
If fg or bg color is not provided, default one should be used.

A color mapping name may be defined only once; predefined mappings may be overridden by a user-defined ones.

Colors Key

colors indicates whether colors is enabled for this art (versus plain text). It has a single case-insensitive boolean value: yes (true) or no (false).

  • If colors is present, its value controls colors.
  • If colors is not present but at least one col key exists, colors is considered enabled.
  • If colors is not present and there are no col keys, colors is considered disabled.

Tags

Any line starting with # defines tags: every word on that line that begins with # is a tag. Duplicate tags in the header SHOULD be deduplicated. There can by multiple tag lines.

Header Example

@3a
title A Cool Art
orig-author Some other guy
author Me
author You
;; This is another comment
editor nvim
license CC0-1.0
preview 3
loop no
src https://example.com/my-cool-art
delay 10 2:100
#ascii #ansi
#art
colors yes
col + bg:bright-red fg:196

Body Block

The body is the block that contains the art itself.
It must always be a last block, so it may include blank lines.

The body consists of frames separated by one or more blank lines. Each frame consists of lines separated by newline.

If colors are enabled and text or colors channels are not pinned, each line is represented by two consecutive rows with equal length:

  • the first is from the text channel
  • the second is the corresponding row from the colors channel

If colors is disabled or pinned, each line corresponds to one row from the text channel.

If text channel is pinned, and colors is enabled. each line corresponds to one row from the colors channel.

If both text or colors channels are pinned or text is pinned and colors are disabled, body is effectively useless and can be omitted.

Body example:

@body
  <=>\      112228111111
  ,..\\..,  111118811111
 ' //     ' 111991111111
|          |111111111111
|          |111111111111
 '.__.~._.' 111111811111

  <=>\      112228111111
  ,..\\..,  111118811111
 ' //,_.--' 11199fffff11
|   /  {    1111f11f1111
|   \_,''-. 1111fffffff1
 '.__.~._.' 111111811111

  <=>\      112228111111
  ,..\\..,  111118811111
 ',--,_.--' 11fffffffff1
    }  {    ffffffffffff
  ,-,_,''-. fffffffffff1
 '.__.~._.' 111111811111

Colors Pin Block

An optional @colors-pin block can be used to pin a single frame for the colors channel.
It consists of a single frame with one row per line.

Example:

@color-pin
112228111111
111118811111
111991111111
111111111111
111111111111
111111811111

Text Pin Block

An optional @text-pin block can be used to pin a single frame for the text channel.
It consists of a single frame with one row per line.

Example:

@text-pin
  <=>\      
  ,..\\..,  
 ' //     ' 
|          |
|          |
 '.__.~._.' 

Attached Block

An optional @attach block can be used to provide arbitrary data attached to art. It consists of single line with any text, but typically JSON.
This block is added for compatibility with "extra" key in durformat.

Example:

@attach
{ "key": "value" }

Extending

The 3a format can be extended with custom blocks and header keys. Extension names must follow the Java package naming convention.

Formatting and Optimization

Recommendations for automatic formatting and optimization of 3a files:

  • Strip redundant header keys and block titles unless specified otherwise below.
  • Preserve comments unless the user explicitly requests they be removed.
  • Comment lines in the header that immediately precede a key line are considered "attached" to that key and should be moved together when reformatting. Keys with attached comments should not be stripped even if they would otherwise be redundant.
  • Remove all content that should be ignored during parsing (e.g., \r characters, frame-specific delay values for non-existent frames), except for comments which should be preserved as above.
  • Convert case-insensitive strings to lowercase.

MIME

Suggested MIME type for 3a is text/x-aaa.

Legacy Format

The current version of 3a can be distinguished from the legacy format by the presence (or absence) of width & height parameters in the legacy header.

Compatibility Notes

The 3a specification fully supports Unicode, but not all rendering software (terminal emulators, etc.) supports all Unicode features. To maximize compatibility:

  • Avoid using grapheme clusters that contain more than one code point in art.
  • Avoid features added in very recent Unicode releases if broad compatibility is required.