-
-
Notifications
You must be signed in to change notification settings - Fork 20
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #74 from DannyBen/add/component
Add `Victor::Component` for component-driven SVG composition
- Loading branch information
Showing
15 changed files
with
287 additions
and
55 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,7 +1,11 @@ | ||
require 'victor/version' | ||
require 'victor/marshaling' | ||
require 'victor/svg_base' | ||
require 'victor/svg' | ||
require 'victor/attributes' | ||
require 'victor/css' | ||
require 'victor/dsl' | ||
|
||
module Victor | ||
autoload :Attributes, 'victor/attributes' | ||
autoload :Component, 'victor/component' | ||
autoload :CSS, 'victor/css' | ||
autoload :DSL, 'victor/dsl' | ||
autoload :Marshaling, 'victor/marshaling' | ||
autoload :SVG, 'victor/svg' | ||
autoload :SVGBase, 'victor/svg_base' | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,61 @@ | ||
require 'forwardable' | ||
|
||
module Victor | ||
class Component | ||
extend Forwardable | ||
include Marshaling | ||
|
||
def_delegators :svg, :save, :render, :content, :element, :css, :to_s | ||
|
||
# Marshaling data | ||
def marshaling = %i[width height x y svg merged_css] | ||
|
||
# Subclasses MUST implement this | ||
def body | ||
raise(NotImplementedError, "#{self.class.name} must implement `body'") | ||
end | ||
|
||
# Subclasses MUST override these methods, OR assign instance vars | ||
def height | ||
@height || raise(NotImplementedError, | ||
"#{self.class.name} must implement `height' or `@height'") | ||
end | ||
|
||
def width | ||
@width || raise(NotImplementedError, | ||
"#{self.class.name} must implement `width' or `@width'") | ||
end | ||
|
||
# Subclasses MAY override these methods, OR assign instance vars | ||
def style = @style ||= {} | ||
def x = @x ||= 0 | ||
def y = @y ||= 0 | ||
|
||
# Appending/Embedding - DSL for the `#body` implementation | ||
def append(component) | ||
svg_instance.append component.svg | ||
merged_css.merge! component.merged_css | ||
end | ||
alias embed append | ||
|
||
# SVG / CSS | ||
def svg | ||
@svg ||= begin | ||
body | ||
svg_instance.css = merged_css | ||
svg_instance | ||
end | ||
end | ||
|
||
protected | ||
|
||
# Start with an ordinary SVG instance | ||
def svg_instance = @svg_instance ||= SVG.new(viewBox: "#{x} #{y} #{width} #{height}") | ||
|
||
# Internal DSL to enable `add.anything` in the `#body` implementation | ||
alias add svg_instance | ||
|
||
# Start with a copy of our own style | ||
def merged_css = @merged_css ||= style.dup | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,39 +1,33 @@ | ||
module Victor | ||
module Marshaling | ||
def marshaling | ||
raise NotImplementedError, "#{self.class.name} must implement `marshaling'" | ||
end | ||
|
||
# YAML serialization methods | ||
def encode_with(coder) | ||
coder['template'] = @template | ||
coder['glue'] = @glue | ||
coder['svg_attributes'] = @svg_attributes | ||
coder['css'] = @css | ||
coder['content'] = @content | ||
marshaling.each do |attr| | ||
coder[attr.to_s] = send(attr) | ||
end | ||
end | ||
|
||
def init_with(coder) | ||
@template = coder['template'] | ||
@glue = coder['glue'] | ||
@svg_attributes = coder['svg_attributes'] | ||
@css = coder['css'] | ||
@content = coder['content'] | ||
marshaling.each do |attr| | ||
instance_variable_set(:"@#{attr}", coder[attr.to_s]) | ||
end | ||
end | ||
|
||
# Marshal serialization methods | ||
def marshal_dump | ||
{ | ||
template: @template, | ||
glue: @glue, | ||
svg_attributes: @svg_attributes, | ||
css: @css, | ||
content: @content, | ||
} | ||
marshaling.to_h do |attr| | ||
[attr, send(attr)] | ||
end | ||
end | ||
|
||
def marshal_load(data) | ||
@template = data[:template] | ||
@glue = data[:glue] | ||
@svg_attributes = data[:svg_attributes] | ||
@css = data[:css] | ||
@content = data[:content] | ||
marshaling.each do |attr| | ||
instance_variable_set(:"@#{attr}", data[attr]) | ||
end | ||
end | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
<svg viewBox="0 0 100 100" width="100%" height="100%" xmlns="http://www.w3.org/2000/svg"> | ||
<style> | ||
.one { | ||
stroke: magenta; | ||
} | ||
.two { | ||
stroke: magenta; | ||
} | ||
.three { | ||
stroke: magenta; | ||
} | ||
</style> | ||
|
||
<g transform="translate(10, 10)"> | ||
<text> | ||
Two | ||
</text> | ||
<text> | ||
Tada | ||
</text> | ||
</g> | ||
</svg> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,9 +1,5 @@ | ||
<svg width="100%" height="100%" | ||
xmlns="http://www.w3.org/2000/svg" | ||
xmlns:xlink="http://www.w3.org/1999/xlink"> | ||
|
||
<svg width="100%" height="100%" xmlns="http://www.w3.org/2000/svg"> | ||
|
||
<circle radius="10"/> | ||
<circle radius="20"/> | ||
|
||
</svg> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,8 +1,4 @@ | ||
<svg width="100%" height="100%" | ||
xmlns="http://www.w3.org/2000/svg" | ||
xmlns:xlink="http://www.w3.org/1999/xlink"> | ||
|
||
<svg width="100%" height="100%" xmlns="http://www.w3.org/2000/svg"> | ||
|
||
<circle radius="10"/><circle radius="20"/> | ||
|
||
</svg> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,33 @@ | ||
module ComponentSet1 | ||
class Base < Victor::Component | ||
def width = 100 | ||
def height = 100 | ||
end | ||
|
||
class Main < Base | ||
def body | ||
add.g transform: 'translate(10, 10)' do | ||
append Two.new | ||
end | ||
end | ||
|
||
def style = { '.one': { stroke: :magenta } } | ||
end | ||
|
||
class Two < Base | ||
def body | ||
add.text 'Two' | ||
append Three.new | ||
end | ||
|
||
def style = { '.two': { stroke: :magenta } } | ||
end | ||
|
||
class Three < Base | ||
def body | ||
add.text 'Tada' | ||
end | ||
|
||
def style = { '.three': { stroke: :magenta } } | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,103 @@ | ||
describe Victor::Component do | ||
describe '#body' do | ||
it 'raises a NotImplementedError' do | ||
expect { subject.body }.to raise_error(NotImplementedError) | ||
end | ||
end | ||
|
||
describe '#height' do | ||
it 'raises a NotImplementedError' do | ||
expect { subject.height }.to raise_error(NotImplementedError) | ||
end | ||
end | ||
|
||
describe '#width' do | ||
it 'raises a NotImplementedError' do | ||
expect { subject.width }.to raise_error(NotImplementedError) | ||
end | ||
end | ||
|
||
describe '#style' do | ||
it 'returns an empty hash' do | ||
expect(subject.style).to eq({}) | ||
end | ||
end | ||
|
||
describe '#x' do | ||
it 'returns 0' do | ||
expect(subject.x).to eq 0 | ||
end | ||
end | ||
|
||
describe '#y' do | ||
it 'returns 0' do | ||
expect(subject.y).to eq 0 | ||
end | ||
end | ||
|
||
context 'when all required methods are implemented' do | ||
let(:svg) do | ||
double save: true, render: true, content: true, element: true, to_s: true | ||
end | ||
|
||
before do | ||
allow(subject).to receive_messages(body: nil, width: 100, height: 100) | ||
allow(subject).to receive(:svg).and_return(svg) | ||
end | ||
|
||
describe '#save' do | ||
it 'delegates to SVG' do | ||
expect(svg).to receive(:save).with('filename') | ||
subject.save 'filename' | ||
end | ||
end | ||
|
||
describe '#render' do | ||
it 'delegates to SVG' do | ||
expect(svg).to receive(:render).with(template: :minimal) | ||
subject.render template: :minimal | ||
end | ||
end | ||
|
||
describe '#content' do | ||
it 'delegates to SVG' do | ||
expect(svg).to receive(:content) | ||
subject.content | ||
end | ||
end | ||
|
||
describe '#element' do | ||
it 'delegates to SVG' do | ||
expect(svg).to receive(:element).with(:rect) | ||
subject.element :rect | ||
end | ||
end | ||
|
||
describe '#to_s' do | ||
it 'delegates to SVG' do | ||
expect(svg).to receive(:to_s) | ||
subject.to_s | ||
end | ||
end | ||
|
||
describe '#append' do | ||
let(:component) { double svg: 'mocked_svg', merged_css: { color: 'red' } } | ||
let(:svg_instance) { double append: true } | ||
let(:merged_css) { double merge!: true } | ||
|
||
it 'appends another component and merges its css' do | ||
allow(subject).to receive_messages(svg_instance: svg_instance, merged_css: merged_css) | ||
expect(svg_instance).to receive(:append).with('mocked_svg') | ||
expect(merged_css).to receive(:merge!).with({ color: 'red' }) | ||
|
||
subject.append component | ||
end | ||
end | ||
|
||
describe '#embed' do | ||
it 'is an alias to #append' do | ||
expect(subject.method(:embed)).to eq subject.method(:append) | ||
end | ||
end | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
require_relative '../fixtures/components/component_set1' | ||
|
||
describe 'Component subclassing' do | ||
subject { ComponentSet1::Main.new } | ||
|
||
describe '#render' do | ||
it 'returns the expected SVG' do | ||
expect(subject.render).to match_approval 'component/set1/render' | ||
end | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
describe Victor::Marshaling do | ||
subject do | ||
Class.new do | ||
include Victor::Marshaling | ||
end.new | ||
end | ||
|
||
describe '#marshaling' do | ||
it 'raises a NotImplementedError' do | ||
expect { subject.marshaling }.to raise_error(NotImplementedError) | ||
end | ||
end | ||
end |
Oops, something went wrong.