1. Purpose

Canon provides environment variable support that works uniformly across all three interfaces: CLI, Ruby API, and RSpec. This allows you to configure Canon behavior through your environment without changing code or command-line arguments.

Environment variables are particularly useful for:

  • Setting defaults across multiple test runs

  • Configuring CI/CD pipelines

  • Temporary overrides without code changes

  • System-wide configuration preferences

2. Environment Variable Naming

Canon uses a hierarchical naming scheme for environment variables:

2.1. Global Variables

Global variables apply to all formats (XML, HTML, JSON, YAML):

CANON_{ATTRIBUTE_NAME}
Example 1. Global environment variable example
export CANON_USE_COLOR=false
export CANON_ALGORITHM=semantic
export CANON_MAX_FILE_SIZE=10485760

2.2. Format-Specific Variables

Format-specific variables apply only to a particular format and override global variables:

CANON_{FORMAT}_{CONFIG_TYPE}_{ATTRIBUTE_NAME}

Where:

  • {FORMAT} is one of: XML, HTML, JSON, YAML

  • {CONFIG_TYPE} is one of: DIFF, MATCH, FORMAT

  • {ATTRIBUTE_NAME} is the configuration attribute

Example 2. Format-specific environment variable example
# XML-specific diff configuration
export CANON_XML_DIFF_ALGORITHM=semantic
export CANON_XML_DIFF_USE_COLOR=true

# HTML-specific match configuration
export CANON_HTML_MATCH_PROFILE=rendered

# JSON-specific preprocessing
export CANON_JSON_FORMAT_PREPROCESSING=normalize

3. Complete Environment Variables Reference

3.1. Diff Configuration Variables

Variable Name Type Default Description Applies To

CANON_MODE

symbol

:by_line

Diff output mode: by_line, by_object, or rspec

All formats

CANON_DISPLAY_PREPROCESSING

symbol

:none

How documents are normalized for display before the line diff: none, pretty_print, c14n. Format-specific: CANON_{FORMAT}_DIFF_DISPLAY_PREPROCESSING

All formats

CANON_PRETTY_PRINTER_INDENT

integer

2

Indentation depth used by the pretty-printer when display_preprocessing: :pretty_print. Format-specific: CANON_{FORMAT}_DIFF_PRETTY_PRINTER_INDENT

All formats (display only)

CANON_PRETTY_PRINTER_INDENT_TYPE

symbol

:space

Indentation character for the pretty-printer: space or tab. Format-specific: CANON_{FORMAT}_DIFF_PRETTY_PRINTER_INDENT_TYPE

All formats (display only)

CANON_XML_DIFF_COLLAPSE_WHITESPACE_ELEMENTS

string array

[]

Comma-separated list of XML element names whose inter-element whitespace is presence-significant but form-insensitive: both " " and "\n " collapse to a single . Suitable for inline mixed-content elements such as <p>, <li>, <td>. Only applies when display_preprocessing: :normalize_pretty_print. Format-specific; no global form.

XML (display only)

CANON_XML_DIFF_PRESERVE_WHITESPACE_ELEMENTS

string array

[]

Comma-separated list of XML element names where every whitespace character is significant and visualized verbatim (" ", "\n "↵░░). Suitable for preformatted elements such as <pre>, <code>. Only applies when display_preprocessing: :normalize_pretty_print. Format-specific; no global form.

XML (display only)

CANON_XML_DIFF_STRIP_WHITESPACE_ELEMENTS

string array

[]

Comma-separated list of XML element names where whitespace-only text nodes are stripped entirely. Only applies when display_preprocessing: :normalize_pretty_print. Format-specific; no global form.

XML (display only)

CANON_XML_DIFF_PRETTY_PRINTED_EXPECTED

boolean

false

When true, whitespace-only text nodes that start with "\n" inside :collapse-classified elements are dropped from the expected (fixture) document before it reaches the line diff. Solves the asymmetric case where the expected side is a hand-indented heredoc fixture but the received side is compact programmatic XML. Only applies when display_preprocessing: :normalize_pretty_print. Format-specific; no global form. See also Pretty-printed fixture support.

XML (display only)

CANON_XML_DIFF_PRETTY_PRINTED_RECEIVED

boolean

false

Same as CANON_XML_DIFF_PRETTY_PRINTED_EXPECTED but applied to the received (actual) document. Useful when the received output may be pretty-printed but the fixture is compact. Format-specific; no global form.

XML (display only)

CANON_XML_DIFF_PRETTY_PRINTER_SORT_ATTRIBUTES

boolean

false

When true, attributes on each element are sorted by namespace URI then local name in the pretty-printed display. Eliminates spurious diff lines caused by differing attribute order between expected and received XML. Only applies when display_preprocessing is :pretty_print or :normalize_pretty_print. Format-specific; no global form.

XML (display only)

CANON_SHOW_RAW_INPUTS

boolean

false

Show the raw (un-preprocessed) file contents of both sides before the diff output. Equivalent to enabling both CANON_SHOW_RAW_EXPECTED and CANON_SHOW_RAW_RECEIVED. Format-specific: CANON_{FORMAT}_DIFF_SHOW_RAW_INPUTS

All formats (display only)

CANON_SHOW_RAW_EXPECTED

boolean

false

Show only the EXPECTED (fixture) block in the raw-inputs section. Has no effect unless show_raw_inputs or verbose_diff is also set. Format-specific: CANON_{FORMAT}_DIFF_SHOW_RAW_EXPECTED

All formats (display only)

CANON_SHOW_RAW_RECEIVED

boolean

false

Show only the RECEIVED (actual) block in the raw-inputs section. Format-specific: CANON_{FORMAT}_DIFF_SHOW_RAW_RECEIVED

All formats (display only)

CANON_SHOW_PREPROCESSED_INPUTS

boolean

false

Show the preprocessed (post-comparison-preprocessing) contents of both sides before the diff output. Equivalent to enabling both CANON_SHOW_PREPROCESSED_EXPECTED and CANON_SHOW_PREPROCESSED_RECEIVED. Format-specific: CANON_{FORMAT}_DIFF_SHOW_PREPROCESSED_INPUTS

All formats (display only)

CANON_SHOW_PREPROCESSED_EXPECTED

boolean

false

Show only the EXPECTED (fixture) block in the preprocessed-inputs section. Has no effect unless show_preprocessed_inputs or verbose_diff is also set. Format-specific: CANON_{FORMAT}_DIFF_SHOW_PREPROCESSED_EXPECTED

All formats (display only)

CANON_SHOW_PREPROCESSED_RECEIVED

boolean

false

Show only the RECEIVED (actual) block in the preprocessed-inputs section. Format-specific: CANON_{FORMAT}_DIFF_SHOW_PREPROCESSED_RECEIVED

All formats (display only)

CANON_SHOW_PRETTYPRINT_INPUTS

boolean

false

Show a fixture-ready pretty-printed form of both original input sides before the diff output. The output is formatted with one XML/HTML tag per line and proper indentation (using the configured pretty_printer_indent / pretty_printer_indent_type), but with no character visualization — whitespace appears as plain ASCII so the output can be copy-pasted directly into RSpec heredoc fixtures. Unlike show_preprocessed_inputs, this always pretty-prints the original strings regardless of the preprocessing or display_preprocessing settings. Equivalent to enabling both CANON_SHOW_PRETTYPRINT_EXPECTED and CANON_SHOW_PRETTYPRINT_RECEIVED. Format-specific: CANON_{FORMAT}_DIFF_SHOW_PRETTYPRINT_INPUTS

All formats (display only)

CANON_SHOW_PRETTYPRINT_EXPECTED

boolean

false

Show only the EXPECTED (fixture) block in the fixture-ready pretty-printed section. Use this to see the current fixture re-formatted for copy-pasting when the fixture is the side that needs updating. Format-specific: CANON_{FORMAT}_DIFF_SHOW_PRETTYPRINT_EXPECTED

All formats (display only)

CANON_SHOW_PRETTYPRINT_RECEIVED

boolean

false

Show only the RECEIVED (actual) block in the fixture-ready pretty-printed section. This is the most common fixture-update workflow: enable this option to get a copy-pasteable pretty-printed form of the generated output that can replace the old fixture heredoc. Format-specific: CANON_{FORMAT}_DIFF_SHOW_PRETTYPRINT_RECEIVED.

For HTML / HTML4 / HTML5 inputs, the pretty-printed output is XHTML-shaped: void elements are self-closed (<br/>, <meta/>), non-void elements are paired (<a></a>), and Nokogiri may add xmlns="http://www.w3.org/1999/xhtml" on <html> and an xml:lang mirror of lang. This is a display-only serialisation chosen because libxml’s FORMAT save flag (the only path that actually indents HTML5 input) requires the XHTML save mode — Nokogiri::HTML5#to_html silently ignores its indent: keyword. See lutaml/canon#133.

All formats (display only)

CANON_COMPACT_SEMANTIC_REPORT

boolean

false

Render element nodes in the Semantic Diff Report as compact inline XML (e.g. <strong>Annex</strong>) instead of the verbose node_info description string (e.g. name: strong namespace_uri: …). Useful when reading Semantic Diff output in the terminal and wanting to see the actual XML markup rather than a textual node description. See format-specific form CANON_{FORMAT}_DIFF_COMPACT_SEMANTIC_REPORT.

All formats (display only)

CANON_CHARACTER_VISUALIZATION

symbol

true

Replace invisible characters with visible Unicode symbols in diff output: true, false, or content_only. Format-specific: CANON_{FORMAT}_DIFF_CHARACTER_VISUALIZATION. Set to false to keep plain-text output.

All formats (display only)

CANON_USE_COLOR

boolean

true

Enable/disable ANSI color codes in output

All formats

CANON_CONTEXT_LINES

integer

3

Number of context lines around changes

All formats

CANON_GROUPING_LINES

integer

10

Maximum lines between changes to group them

All formats

CANON_SHOW_DIFFS

symbol

:all

Which diffs to show: all, normative, informative

All formats

CANON_VERBOSE_DIFF

boolean

false

Enable verbose diff output with detailed analysis

All formats

CANON_ALGORITHM

symbol

:dom

Diff algorithm: dom (positional) or semantic (tree-based)

All formats

CANON_MAX_FILE_SIZE

integer

5242880

Maximum file size in bytes (default 5MB)

All formats

CANON_MAX_NODE_COUNT

integer

10000

Maximum number of nodes in parsed tree

All formats

CANON_MAX_DIFF_LINES

integer

10000

Maximum number of diff output lines

All formats

CANON_DIFF_THEME

symbol

:dark

Diff display theme: light, dark, retro, claude, cyberpunk

All formats

3.2. Match Configuration Variables

Variable Name Type Default Description Applies To

CANON_PROFILE

symbol

nil

Match profile: strict, rendered, spec_friendly, content_only

All formats

3.3. Format Configuration Variables

Variable Name Type Default Description Applies To

CANON_PREPROCESSING

string

none

Preprocessing mode: none, c14n, normalize, format

XML, HTML, JSON, YAML

4. Examples: Same Configuration, Different Interfaces

This section demonstrates how the same configuration is expressed across all three Canon interfaces.

4.1. Example 1: Basic Configuration

Enable semantic diff algorithm with color output.

Using environment variables
export CANON_ALGORITHM=semantic
export CANON_USE_COLOR=true
Using CLI
canon diff file1.xml file2.xml \
  --diff-algorithm semantic \
  --color
Using Ruby API
Canon.compare(file1, file2, format: :xml,
  diff_algorithm: :semantic,
  color: true
)
Using RSpec
RSpec.configure do |config|
  config.canon.xml.diff.algorithm = :semantic
  config.canon.xml.diff.use_color = true
end

4.2. Example 2: Format-Specific Configuration

Configure XML and HTML differently.

Using environment variables
# XML uses semantic diff
export CANON_XML_DIFF_ALGORITHM=semantic
export CANON_XML_MATCH_PROFILE=strict

# HTML uses DOM diff and rendered profile
export CANON_HTML_DIFF_ALGORITHM=dom
export CANON_HTML_MATCH_PROFILE=rendered
Using CLI
# For XML files
canon diff file1.xml file2.xml \
  --diff-algorithm semantic \
  --match-profile strict

# For HTML files
canon diff file1.html file2.html \
  --diff-algorithm dom \
  --match-profile rendered
Using Ruby API
# For XML
Canon.compare(file1_xml, file2_xml, format: :xml,
  diff_algorithm: :semantic,
  match_profile: :strict
)

# For HTML
Canon.compare(file1_html, file2_html, format: :html,
  diff_algorithm: :dom,
  match_profile: :rendered
)
Using RSpec
RSpec.configure do |config|
  # XML configuration
  config.canon.xml.diff.algorithm = :semantic
  config.canon.xml.match.profile = :strict

  # HTML configuration
  config.canon.html.diff.algorithm = :dom
  config.canon.html.match.profile = :rendered
end

4.3. Example 3: Size Limits

Configure file size and node count limits.

Using environment variables
export CANON_MAX_FILE_SIZE=10485760    # 10MB
export CANON_MAX_NODE_COUNT=50000      # 50k nodes
export CANON_MAX_DIFF_LINES=20000      # 20k lines
Using Ruby API
Canon.configure do |config|
  config.xml.diff.max_file_size = 10_485_760
  config.xml.diff.max_node_count = 50_000
  config.xml.diff.max_diff_lines = 20_000
end
Using RSpec
RSpec.configure do |config|
  config.canon.xml.diff.max_file_size = 10_485_760
  config.canon.xml.diff.max_node_count = 50_000
  config.canon.xml.diff.max_diff_lines = 20_000
end
Size limits are not available as CLI options - they must be configured through environment variables or programmatic configuration.

5. Priority Chain

When multiple configuration sources are present, Canon uses the following priority order (highest to lowest):

  1. Explicit arguments - Passed directly to the comparison method or CLI command

  2. Environment variables - Set via CANON_* variables

  3. Default values - Built-in Canon defaults

Example 3. Priority chain example
# Environment variable sets default
export CANON_ALGORITHM=semantic

# CLI argument overrides environment variable
canon diff file1.xml file2.xml --diff-algorithm dom
# Uses: dom (explicit CLI argument wins)

# No CLI argument, environment variable applies
canon diff file1.xml file2.xml
# Uses: semantic (from environment variable)

6. Type Conversion

Canon automatically converts environment variable string values to the appropriate types:

Type Conversion Rules

Boolean

"true", "1", "yes"true
"false", "0", "no"false

Integer

String parsed as decimal integer

Symbol

String converted to symbol (e.g., "semantic":semantic)

7. Debugging Environment Variables

To verify which environment variables Canon is using:

Check active environment variables
env | grep CANON_
Enable verbose output to see configuration
export CANON_VERBOSE_DIFF=true
canon diff file1.xml file2.xml --verbose