Library Mode
require "sevgi" loads two complementary entry points: the global SVG(...) document builder and the SVG facade.
Facade operations use capitalized method names such as SVG.Canvas, SVG.Document, and SVG.Derender; constants and
types use double colons, such as SVG::Canvas. Library code gets this explicit SVG vocabulary without pulling every
Sevgi helper into the application's method scope.
Use the Execution API when library code needs to run a complete trusted .sevgi program rather than
construct a document directly.
Build and compose
require "sevgi"
drawing = SVG :minimal, width: 240, height: 64 do
text "Payment received", x: 52, y: 27, "font-weight": "bold"
text "$48.00", x: 52, y: 46, fill: "#166534"
end
status = SVG :minimal do
g transform: "translate(28 32)" do
circle r: 14, fill: "#16a34a"
path d: "M -6 0 L -2 5 L 7 -6", fill: "none", stroke: "white", "stroke-width": 2
end
end.first
background = SVG(:minimal) { rect width: 240, height: 64, rx: 10, fill: "#f0fdf4" }.first
drawing.Append status
drawing.Prepend background
Append and Prepend transfer existing elements into the document, so independently built fragments can become one
drawing. Here the background moves behind the original text, while the status icon moves after it. The same operations
also reorder elements that already share a parent.
Call drawing.Render when the surrounding application needs the SVG string. If you load only sevgi/graphics, the
component-level constructor is Sevgi::Graphics.SVG.
Facade grammar
The method/constant distinction is deliberate:
require "sevgi"
canvas = SVG.Canvas width: 24, height: 24, unit: :px
drawing = SVG(:minimal, canvas) { circle cx: 12, cy: 12, r: 10 }
canvas.is_a?(SVG::Canvas) # => true
drawing.Render
SVG(...) invokes the global document-builder method. SVG.Canvas(...) invokes a facade operation.
SVG::Canvas names the returned type. The facade does not repeat the receiver as SVG.SVG(...).
The same top-level operations also exist on Sevgi because script execution and include Sevgi use that complete
toolkit surface. Sevgi.SVG(...) and Sevgi.Canvas(...) are valid, but the SVG facade is the canonical receiver for
ordinary SVG library work. Execution stays separate as Sevgi.execute and Sevgi.execute_file.
Canvas and document profiles
Use a Canvas when dimensions, units, margins, and the resulting viewBox belong together. Its size is the outer
paper; inner is the remaining size after margins. The default viewBox shifts by the negative left and top margins, so
drawing coordinate (0, 0) starts at the inner area's top-left while the viewport still includes the margins:
require "sevgi"
canvas = SVG.Canvas :a4, margins: [12, 10]
drawing = SVG :minimal, canvas do
rect width: canvas.inner.width, height: canvas.inner.height
end
A document profile owns SVG root attributes and preambles independently of the physical canvas. Anonymous profiles are useful for one library object. Named profiles belong to a process-wide registry; reserve them for shared vocabulary rather than per-request options. The document-profile matrix compares the four built-in choices and explains the advanced common extension layer.
require "sevgi"
icon = SVG.Document attributes: {viewBox: "0 0 24 24"}
SVG(icon) { circle cx: 12, cy: 12, r: 10 }.Render
SVG.Document :badge, attributes: {viewBox: "0 0 40 16"}
SVG(:badge) { text "OK", x: 20, y: 12, "text-anchor": "middle" }.Render
The first argument to SVG selects the document profile; the optional second argument supplies the canvas. Root keyword
attributes are applied after both. Keep profile and canvas separate when several document dialects share one page size,
or one document dialect is rendered on several sizes.
The same vocabulary with a receiver
The script runner promotes operations such as Paper, Canvas, and Grid into its managed scope. Library code uses
the same capitalized words on the facade:
require "sevgi"
SVG.Paper 85, 55, :card
canvas = SVG.Canvas :card, margins: 4
card = SVG :minimal, canvas do
rect width: "100%", height: "100%", rx: 3
end
File.write("card.svg", card.Render)
The equivalent script drops only the facade receiver: Paper(...) and Canvas(...) become bare words, while
SVG(...) and the drawing block stay unchanged. In library mode, the application usually decides where the rendered
string goes.
Import the full top level
If a class is dedicated to drawing, include Sevgi and use the script-style names inside it:
require "sevgi"
badge = Class.new do
include Sevgi
def render(label)
SVG(:minimal) { text label, x: 4, y: 14 }.Render
end
end
badge.new.render("S")
include Sevgi adds the full top-level API to instances. You do not need it just to call SVG(...) after
require "sevgi".
Focused graphics component
Applications that depend only on sevgi-graphics use its conventional lowercase component API. This focused require
does not install the full SVG facade:
require "sevgi/graphics"
canvas = Sevgi::Graphics.canvas width: 24, height: 24, unit: :px
drawing = Sevgi::Graphics.SVG(:minimal, canvas) { circle cx: 12, cy: 12, r: 10 }
Use this form when the smaller gem dependency is the goal. Do not mix its lowercase constructors into the facade
dialect; SVG.Canvas is the corresponding full-toolkit spelling.
Callable modules
Callable modules keep related drawing steps together without adding global methods. Before passing a module to
Call, Group, Layer,
Layer!, or Symbols, extend it with SVG::Module:
status = Module.new do
extend SVG::Module
base { circle r: 10, fill: "seagreen" }
def call(label:) = text label, y: 4, fill: "white", "text-anchor": "middle"
end
SVG :minimal, width: 24, height: 24 do
g(transform: "translate(12 12)") { Call status, label: "OK" }
end.Render
Module.new creates an ordinary Ruby module. extend SVG::Module makes its public instance methods available as
drawing steps.
Name the method call when the module has one drawing step. If it has several public methods, each method becomes a
separate step. base registers shared, argument-independent drawing that runs before them. The wrapper
word decides whether Sevgi draws the result directly, puts it in a group or layer, or expands it into symbols.
SVG::Module aliases the graphics component's callable-module contract. When loading only sevgi/graphics, the facade
is not installed; use Sevgi::Graphics::Module.
Module namespaces
For a namespace that owns several drawing modules, use extend SVG::Modules. It applies the singular contract to the
namespace and its module constants, including descendants defined later:
module StatusIcons
extend SVG::Modules
module Alert
base { circle r: 5, fill: "tomato" }
def call(x:) = text "!", x:, y: 3, "text-anchor": "middle"
end
module Ready
def call(x:) = circle cx: x, r: 3, fill: "seagreen"
end
end
SVG :minimal do
Call StatusIcons::Alert, x: 5
Call StatusIcons::Ready, x: 15
end.Render
Sevgi leaves classes, autoloads, and modules merely aliased into the namespace alone. Extend an external module with
SVG::Module yourself when it should participate.