Class: Fontisan::Commands::ConvertCommand

Inherits:
BaseCommand
  • Object
show all
Defined in:
lib/fontisan/commands/convert_command.rb

Overview

Command for converting fonts between formats

ConvertCommand provides CLI interface for font format conversion operations using the universal transformation pipeline. It supports:

  • Same-format operations (copy/optimize)
  • TTF ↔ OTF outline format conversion
  • Variable font operations (preserve/instance generation)
  • WOFF/WOFF2 compression

The command uses TransformationPipeline to orchestrate conversions with appropriate strategies.

Examples:

Convert TTF to OTF

command = ConvertCommand.new(
  'input.ttf',
  to: 'otf',
  output: 'output.otf'
)
command.run

Generate instance at coordinates

command = ConvertCommand.new(
  'variable.ttf',
  to: 'ttf',
  output: 'bold.ttf',
  coordinates: 'wght=700,wdth=100'
)
command.run

Convert with ConversionOptions

options = ConversionOptions.recommended(from: :ttf, to: :otf)
command = ConvertCommand.new(
  'input.ttf',
  to: 'otf',
  output: 'output.otf',
  options: options
)
command.run

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(font_path, options = {}) ⇒ ConvertCommand

Initialize convert command

Parameters:

  • font_path (String)

    Path to input font file

  • options (Hash) (defaults to: {})

    Conversion options

Options Hash (options):

  • :to (String, Array<String>)

    Target format(s): ttf, otf, woff, woff2, type1, ttc, otc, dfont, svg. Pass a comma-separated string ("woff,woff2") or an array (["woff", "woff2"]) for multi-format output. Single-font → single-font only; multi-format + collection input is rejected.

  • :output (String)

    Output file path (required)

  • :font_index (Integer)

    Index for TTC/OTC (default: 0)

  • :coordinates (String)

    Coordinate string (e.g., "wght=700,wdth=100")

  • :instance_coordinates (Hash)

    Axis coordinates hash (e.g., => 700.0)

  • :instance_index (Integer)

    Named instance index

  • :preserve_variation (Boolean)

    Preserve variation data (default: auto)

  • :preserve_hints (Boolean)

    Preserve rendering hints (default: false)

  • :target_format (String)

    Target outline format for collections: 'preserve' (default), 'ttf', or 'otf'

  • :no_validate (Boolean)

    Skip output validation

  • :verbose (Boolean)

    Verbose output

  • :options (ConversionOptions)

    ConversionOptions object



70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
# File 'lib/fontisan/commands/convert_command.rb', line 70

def initialize(font_path, options = {})
  super(font_path, options)

  # Convert string keys to symbols for Thor compatibility. All command
  # code reads @options with symbol keys (e.g., @options[:quiet]);
  # normalizing once at construction is cleaner than threading a
  # second opts hash alongside @options.
  @options = options.transform_keys(&:to_sym)

  @output_path = @options[:output]

  # Parse target format(s). Always an Array<Symbol>, deduped, order
  # preserved. Single-format callsites get a one-element array.
  @target_formats = parse_target_formats(@options[:to])

  # Resolve per-format output paths up front so filename ambiguity
  # surfaces before any pipeline work is done.
  @output_paths = resolve_output_paths

  # Extract ConversionOptions if provided
  @conv_options = extract_conversion_options(@options)

  # Parse coordinates if string provided
  @coordinates = if @options[:coordinates]
                   parse_coordinates(@options[:coordinates])
                 elsif @options[:instance_coordinates]
                   @options[:instance_coordinates]
                 end

  @instance_index = @options[:instance_index]
  @preserve_variation = @options[:preserve_variation]
  @preserve_hints = @options.fetch(:preserve_hints, false)
  @collection_target_format = @options.fetch(:target_format,
                                             "preserve").to_s
  @validate = !@options[:no_validate]
end

Instance Attribute Details

#output_pathsObject (readonly)

Public readers for the parsed target formats and per-format output paths. Exposed (rather than relying on @ivar access from specs) so multi-format behaviour can be tested through the public surface.



48
49
50
# File 'lib/fontisan/commands/convert_command.rb', line 48

def output_paths
  @output_paths
end

#target_formatsObject (readonly)

Public readers for the parsed target formats and per-format output paths. Exposed (rather than relying on @ivar access from specs) so multi-format behaviour can be tested through the public surface.



48
49
50
# File 'lib/fontisan/commands/convert_command.rb', line 48

def target_formats
  @target_formats
end

Instance Method Details

#runHash+

Execute the conversion

Returns:

  • (Hash, Array<Hash>)

    Result information. Single-format returns one result hash (back-compat). Multi-format returns an array of result hashes, one per target format.

Raises:

  • (ArgumentError)

    If output path is not specified

  • (Error)

    If conversion fails



114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
# File 'lib/fontisan/commands/convert_command.rb', line 114

def run
  validate_options!

  if collection_file?
    if multi_format?
      raise ArgumentError,
            "Multi-format conversion is not supported for collection " \
            "input. Specify a single target format."
    end

    convert_collection
  elsif multi_format?
    convert_multi_format
  else
    convert_single_font(@target_formats.first, @output_paths.first)
  end
rescue ArgumentError
  # Let ArgumentError propagate for validation errors
  raise
rescue StandardError => e
  raise Error, "Conversion failed: #{e.message}"
end