Class: Sevgi::Graphics::Content Abstract

Inherits:
Object
  • Object
show all
Defined in:
lib/sevgi/graphics/auxiliary/content.rb

Overview

This class is abstract.

Subclasses implement #render and expose their own construction API.

Extensible protocol for renderable text-like content inside an SVG element. Use Content.cdata, Content.css, Content.encoded, or Content.verbatim for built-in content, or subclass Content and implement #render for a custom serialization. Content owns an immutable deep snapshot: strings and containers are copied, mutable leaf objects are stringified once during construction, and #content returns caller-owned copies. Later mutations cannot change rendering or invalidate the construction-time XML checks.

Examples:

Choose a built-in content channel

Sevgi::Graphics.SVG(:minimal) do
  text "A & B" # ordinary String arguments are encoded automatically
  text Sevgi::Graphics::Content.encoded("A & B")
  style Sevgi::Graphics::Content.cdata(".note { fill: red; }")
  style Sevgi::Graphics::Content.css(".note" => {fill: "red"})
  g Sevgi::Graphics::Content.verbatim("<title>trusted markup</title>")
end

Define custom content that emits an SVG tspan

class Emphasis < Sevgi::Graphics::Content
  def self.[](content) = send(:new, content)

  def render(output, depth)
    text = Sevgi::Graphics::Content.encoded(to_s).to_s
    output.append(depth + 1, %(<tspan font-style="italic">#{text}</tspan>))
  end
end

Sevgi::Graphics.SVG(:minimal) { text Emphasis["important & safe"] }.Render

# The renderer ignores Emphasis#render's return value. Custom content must escape inserted data itself.

See Also:

Defined Under Namespace

Classes: CData, CSS, Encoded, Verbatim

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(content) ⇒ void

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Creates immutable content from a deep payload snapshot. Strings and containers are copied recursively; mutable non-container objects are stringified once during construction. The caller's objects are never retained.

Parameters:

  • content (Object)

    wrapped content

Raises:

  • (Sevgi::ArgumentError)

    when content cannot be stringified, contains invalid encoding or illegal XML characters, contains cycles, or has keys that collide after stringification



116
117
118
119
# File 'lib/sevgi/graphics/auxiliary/content.rb', line 116

def initialize(content)
  @content = Snapshot.capture(content)
  XML.validate(@content)
end

Class Method Details

.cdata(content) ⇒ Sevgi::Graphics::Content::CData

Builds CDATA content. Mutable objects are stringified during construction, and embedded CDATA terminators are split safely.

Parameters:

  • content (Object)

    wrapped content

Returns:

Raises:

  • (Sevgi::ArgumentError)

    when content cannot be stringified, contains invalid encoding or illegal XML 1.0 characters, contains cycles, or has keys that collide after stringification



158
# File 'lib/sevgi/graphics/auxiliary/content.rb', line 158

def self.cdata(...) = CData.send(:new, ...)

.css(content) ⇒ Sevgi::Graphics::Content::CSS

Builds CSS content.

Parameters:

  • content (Hash)

    CSS rules

Returns:

Raises:

  • (Sevgi::ArgumentError)

    when content is not a hash, contains a malformed style, cannot be stringified, contains invalid encoding or illegal XML 1.0 characters, contains cycles, or has keys that collide after stringification



167
# File 'lib/sevgi/graphics/auxiliary/content.rb', line 167

def self.css(...) = CSS.send(:new, ...)

.encoded(content) ⇒ Sevgi::Graphics::Content::Encoded

Builds XML text-encoded content. Mutable objects are stringified during construction before XML text escaping.

Parameters:

  • content (Object)

    wrapped content

Returns:

Raises:

  • (Sevgi::ArgumentError)

    when content cannot be stringified, contains invalid encoding or illegal XML 1.0 characters, contains cycles, or has keys that collide after stringification



176
# File 'lib/sevgi/graphics/auxiliary/content.rb', line 176

def self.encoded(...) = Encoded.send(:new, ...)

.verbatim(content) ⇒ Sevgi::Graphics::Content::Verbatim

Builds verbatim content. Mutable objects are stringified during construction.

Parameters:

  • content (Object)

    wrapped content

Returns:

Raises:

  • (Sevgi::ArgumentError)

    when content cannot be stringified, contains invalid encoding or illegal XML 1.0 characters, contains cycles, or has keys that collide after stringification



185
# File 'lib/sevgi/graphics/auxiliary/content.rb', line 185

def self.verbatim(...) = Verbatim.send(:new, ...)

Instance Method Details

#contentObject

Returns a recursively independent, caller-owned payload snapshot.

Returns:

  • (Object)

    wrapped content snapshot



107
# File 'lib/sevgi/graphics/auxiliary/content.rb', line 107

def content = Snapshot.copy(@content)

#render(_output, _depth) ⇒ Object

This method is abstract.

Subclasses implement content rendering.

Appends this content's serialized XML lines to rendering output. The output collaborator responds to append(depth, *lines), where depth is an Integer or nil and every line is a String containing valid serialized XML text. The rendering engine ignores both append and render return values. Custom content is responsible for escaping data that it inserts into markup.

Parameters:

  • _output (#append)

    rendering output collaborator

  • _depth (Integer)

    current render depth

Returns:

  • (Object)

    ignored by the rendering engine

Raises:

  • (Sevgi::PanicError)

    when a subclass does not implement render



141
# File 'lib/sevgi/graphics/auxiliary/content.rb', line 141

def render(_output, _depth) = PanicError.("#{self.class}#render must be implemented")

#to_sString

Returns content as a string.

Returns:

  • (String)


145
# File 'lib/sevgi/graphics/auxiliary/content.rb', line 145

def to_s = XML.text(payload)