Module: Sevgi::Sundries::Export

Extended by:
Export
Included in:
Export
Defined in:
lib/sevgi/sundries/export.rb,
lib/sevgi/sundries/export/native.rb,
lib/sevgi/sundries/export/system.rb

Overview

Exports SVG source to PNG or PDF and post-processes PDF output.

Native PDF/PNG rendering is loaded lazily so installing sevgi-sundries for SVG-only helpers does not require the Cairo, RSVG, or HexaPDF gems. Native export entrypoints raise MissingComponentError when those optional gems are unavailable. Omit format: to infer it from the output suffix; width and height are output dimensions rather than changes to the SVG viewBox. The return value is the expanded path that was written.

Examples:

Export SVG source to a sized PNG

svg = Sevgi::Graphics.SVG(:minimal) { circle cx: 5, cy: 5, r: 4 }.Render
Sevgi::Sundries::Export.call(svg, "drawing.png", width: 320)

Infer PDF output and inject export-only CSS

svg = Sevgi::Graphics.SVG(:minimal) { circle class: "accent", r: 4 }.Render
Sevgi::Sundries::Export.call(svg, "drawing.pdf", css: ".accent { fill: tomato; }")

See Also:

Constant Summary collapse

AVAILABLE =

Supported export format names mapped to file extensions.

EXTENSIONS.invert.freeze
DEFAULT_DPI =

Default SVG CSS pixel density.

96.0
ExportError =

Raised when SVG export or PDF post-processing cannot be completed.

Class.new(Error)

Instance Method Summary collapse

Instance Method Details

#a5_on_a4(infile, outfile) ⇒ Sevgi::Function::Shell::Result

Places a single A5 PDF page twice on an A4 landscape sheet with pdfcpu.

Parameters:

  • infile (String)

    source PDF file path

  • outfile (String)

    destination PDF file path

Returns:

  • (Sevgi::Function::Shell::Result)

    command result

Raises:

  • (Sevgi::Error)

    when pdfcpu is missing or the command fails

  • (Errno::ENOENT)

    when the executable cannot be spawned

See Also:



16
# File 'lib/sevgi/sundries/export/system.rb', line 16

def a5_on_a4(infile, outfile) = F.sh!("pdfcpu", "nup", "--", "form:A4L, border:off", outfile, "2", infile)

#a5_on_a4!(infile) ⇒ void

This method returns an undefined value.

Replaces a PDF file with an A5-on-A4 layout generated by pdfcpu.

Parameters:

  • infile (String)

    PDF file path to modify

Raises:

  • (Sevgi::Error)

    when pdfcpu is missing or the command fails

  • (Errno::ENOENT)

    when the executable cannot be spawned



23
24
25
26
27
28
29
# File 'lib/sevgi/sundries/export/system.rb', line 23

def a5_on_a4!(infile)
  temp = Tempfile.new(%w[output .pdf], File.dirname(infile))
  a5_on_a4(infile, temp.path)
  FileUtils.mv(temp.path, infile)
ensure
  temp&.close!
end

#call(svg, output, format: nil, width: nil, height: nil, dpi: DEFAULT_DPI, css: nil) {|svg| ... } ⇒ String

Exports SVG source to a PDF or PNG file using librsvg and Cairo. Relative paths are expanded, missing parent directories are created after all render inputs validate, and an existing output file is replaced. Directory paths are not expanded to a default file name.

Parameters:

  • svg (String)

    SVG source content

  • output (String, #to_path)

    output file path

  • format (Symbol, String, nil) (defaults to: nil)

    explicit output format, or nil to infer from output extension

  • width (Numeric, nil) (defaults to: nil)

    finite positive target width in output pixels for PNG, or CSS pixels before PDF point conversion

  • height (Numeric, nil) (defaults to: nil)

    finite positive target height in output pixels for PNG, or CSS pixels before PDF point conversion

  • dpi (Numeric) (defaults to: DEFAULT_DPI)

    finite positive CSS pixel density; omission uses DEFAULT_DPI, but explicit nil is invalid

  • css (String, nil) (defaults to: nil)

    CSS inserted before the closing svg tag before rendering

Yields:

  • (svg)

    optional source transformation applied before rendering

Yield Parameters:

  • svg (String)

    SVG source after optional CSS injection

Yield Returns:

  • (String)

    SVG source to render

Returns:

  • (String)

    expanded output path

Raises:

  • (Sevgi::ArgumentError)

    when output is blank, invalid, or a directory, or CSS/transformed SVG has an invalid type

  • (Sevgi::Sundries::Export::ExportError)

    when format, numeric options, CSS insertion, SVG parsing, SVG dimensions, or render dimensions are invalid

  • (SystemCallError)

    when the output directory or file cannot be created or written



70
# File 'lib/sevgi/sundries/export.rb', line 70

def call(*args, **kwargs, &block) = native!.call(*args, **kwargs, &block)

#inkscape(infile, outfile = nil, format: nil, background: "#ffffff", opacity: 1, width: nil, height: nil, id: nil, page: nil, css: nil) ⇒ Sevgi::Function::Shell::Result

Exports an SVG file through Inkscape.

Parameters:

  • infile (String)

    source SVG file path

  • outfile (String, nil) (defaults to: nil)

    output path, defaulting to infile with a .pdf extension

  • format (Symbol, String, nil) (defaults to: nil)

    explicit output format, or nil to infer from outfile

  • background (String, nil) (defaults to: "#ffffff")

    export background color

  • opacity (Numeric, nil) (defaults to: 1)

    export background opacity

  • width (Numeric, nil) (defaults to: nil)

    target export width

  • height (Numeric, nil) (defaults to: nil)

    target export height

  • id (String, nil) (defaults to: nil)

    SVG element id to export

  • page (Integer, String, nil) (defaults to: nil)

    page selector passed to Inkscape

  • css (String, nil) (defaults to: nil)

    CSS inserted before exporting

Returns:

  • (Sevgi::Function::Shell::Result)

    command result

Raises:

  • (Sevgi::Sundries::Export::ExportError)

    when format, output extension, or CSS insertion is invalid

  • (Sevgi::Error)

    when Inkscape is missing or the command fails

  • (Errno::ENOENT)

    when the executable cannot be spawned

See Also:



47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
# File 'lib/sevgi/sundries/export/system.rb', line 47

def inkscape(
  infile,
  outfile = nil,
  format: nil,
  background: "#ffffff",
  opacity: 1,
  width: nil,
  height: nil,
  id: nil,
  page: nil,
  css: nil
)
  infile = File.expand_path(infile)
  outfile ||= F.subext(".pdf", infile)
  outfile = File.expand_path(outfile)
  format = format_for(format, outfile)

  if css
    temp = Tempfile.new(%w[input .svg], File.dirname(infile))
    ::File.write(temp.path, styled(::File.read(infile), css))
    infile = temp.path
  end

  F.sh!(
    *[
      "inkscape",
      "--batch-process",
      "--actions=select-by-class:text,object-to-path",
      "--export-type=#{format}",
      ("--export-background=#{background}" if background),
      ("--export-background-opacity=#{opacity}" if opacity),
      ("--export-width=#{width}" if width),
      ("--export-height=#{height}" if height),
      ("--export-id=#{id}" if id),
      ("--export-id-only" if id),
      ("--export-page=#{page}" if page),
      "--export-filename=#{outfile}",
      infile
    ].compact
  )
ensure
  temp&.close!
end

#rsvg(infile, outfile = nil, format: nil, background: "#ffffff", width: nil, height: nil, id: nil, css: nil) ⇒ Sevgi::Function::Shell::Result

Exports an SVG file through rsvg-convert.

Parameters:

  • infile (String)

    source SVG file path

  • outfile (String, nil) (defaults to: nil)

    output path, defaulting to infile with a .pdf extension

  • format (Symbol, String, nil) (defaults to: nil)

    explicit output format, or nil to infer from outfile

  • background (String, nil) (defaults to: "#ffffff")

    export background color

  • width (Numeric, nil) (defaults to: nil)

    target export width

  • height (Numeric, nil) (defaults to: nil)

    target export height

  • id (String, nil) (defaults to: nil)

    SVG element id to export

  • css (String, nil) (defaults to: nil)

    CSS inserted before exporting

Returns:

  • (Sevgi::Function::Shell::Result)

    command result

Raises:

  • (Sevgi::Sundries::Export::ExportError)

    when format, output extension, or CSS insertion is invalid

  • (Sevgi::Error)

    when rsvg-convert is missing or the command fails

  • (Errno::ENOENT)

    when the executable cannot be spawned

See Also:



105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
# File 'lib/sevgi/sundries/export/system.rb', line 105

def rsvg(
  infile,
  outfile = nil,
  format: nil,
  background: "#ffffff",
  width: nil,
  height: nil,
  id: nil,
  css: nil
)
  infile = File.expand_path(infile)
  outfile ||= F.subext(".pdf", infile)
  outfile = File.expand_path(outfile)
  format = format_for(format, outfile)

  if css
    temp = Tempfile.new(%w[input .svg], File.dirname(infile))
    ::File.write(temp.path, styled(::File.read(infile), css))
    infile = temp.path
  end

  F.sh!(
    *[
      "rsvg-convert",
      "--format=#{format}",
      ("--background-color=#{background}" if background),
      ("--width=#{width}" if width),
      ("--height=#{height}" if height),
      ("--export-id=#{id}" if id),
      "--output=#{outfile}",
      infile
    ].compact
  )
ensure
  temp&.close!
end

#stamp(infile, outfile, stamp:, placeholder:) ⇒ Boolean

Note:

Streams with unbalanced graphics-state or text-object operators are left unchanged.

Replaces exact placeholder text objects in PDF streams. The placeholder must appear as a PDF literal string in a white text object matching the export stamp pattern. Replacement text is escaped as a PDF literal string. When no exact match is replaced, the output file is not written.

Parameters:

  • infile (String)

    source PDF file path

  • outfile (String)

    destination PDF file path

  • stamp (String)

    replacement text

  • placeholder (String)

    placeholder text to replace

Returns:

  • (Boolean)

    true when at least one matching placeholder was replaced

Raises:



112
# File 'lib/sevgi/sundries/export.rb', line 112

def stamp(infile, outfile, stamp:, placeholder:) = native!.stamp(infile, outfile, stamp:, placeholder:)

#stamp!(infile, stamp:, placeholder:) ⇒ Boolean

Note:

Streams with unbalanced graphics-state or text-object operators are left unchanged.

Replaces exact placeholder text objects inside a PDF file in place. The input file is replaced only after at least one exact placeholder match is rewritten into a non-empty output file.

Parameters:

  • infile (String)

    PDF file path to modify

  • stamp (String)

    replacement text

  • placeholder (String)

    placeholder text to replace

Returns:

  • (Boolean)

    true when at least one matching placeholder was replaced

Raises:



122
# File 'lib/sevgi/sundries/export.rb', line 122

def stamp!(infile, stamp:, placeholder:) = native!.stamp!(infile, stamp:, placeholder:)

#unite(sources, outfile) ⇒ Sevgi::Function::Shell::Result

Merges PDF files with pdfunite.

Parameters:

  • sources (Array<String>)

    source PDF file paths

  • outfile (String)

    destination PDF file path

Returns:

  • (Sevgi::Function::Shell::Result)

    command result

Raises:

  • (Sevgi::Error)

    when pdfunite is missing or the command fails

  • (Errno::ENOENT)

    when the executable cannot be spawned

See Also:



149
# File 'lib/sevgi/sundries/export/system.rb', line 149

def unite(sources, outfile) = F.sh!("pdfunite", *sources, outfile)