Refactor AsciicastDecorator#thumbnail to render colorful thumbnail
parent
86f728364c
commit
d93ac84c21
@ -0,0 +1,22 @@
|
|||||||
|
class SnapshotFragment
|
||||||
|
|
||||||
|
attr_reader :text, :brush
|
||||||
|
|
||||||
|
def initialize(text, brush)
|
||||||
|
@text = text
|
||||||
|
@brush = brush
|
||||||
|
end
|
||||||
|
|
||||||
|
def ==(other)
|
||||||
|
other.text == text && other.brush == brush
|
||||||
|
end
|
||||||
|
|
||||||
|
def crop(size)
|
||||||
|
if size >= text.size
|
||||||
|
self
|
||||||
|
else
|
||||||
|
self.class.new(text[0...size], brush)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
@ -0,0 +1,31 @@
|
|||||||
|
class SnapshotLine
|
||||||
|
|
||||||
|
attr_reader :fragments
|
||||||
|
|
||||||
|
def initialize(fragments)
|
||||||
|
@fragments = fragments
|
||||||
|
end
|
||||||
|
|
||||||
|
def ==(other)
|
||||||
|
other.fragments == fragments
|
||||||
|
end
|
||||||
|
|
||||||
|
def crop(size)
|
||||||
|
new_fragments = []
|
||||||
|
current_size = 0
|
||||||
|
|
||||||
|
fragments.each do |fragment|
|
||||||
|
break if current_size == size
|
||||||
|
|
||||||
|
if current_size + fragment.size > size
|
||||||
|
fragment = fragment.crop(size - current_size)
|
||||||
|
end
|
||||||
|
|
||||||
|
new_fragments << fragment
|
||||||
|
current_size += fragment.size
|
||||||
|
end
|
||||||
|
|
||||||
|
self.class.new(new_fragments)
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
@ -0,0 +1,33 @@
|
|||||||
|
class BrushPresenter < SimpleDelegator
|
||||||
|
|
||||||
|
def to_css_class
|
||||||
|
if default?
|
||||||
|
nil
|
||||||
|
else
|
||||||
|
[fg_class, bg_class, bold_class, underline_class, inverse_class].compact.join(' ')
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
private
|
||||||
|
|
||||||
|
def fg_class
|
||||||
|
"fg#{fg}" if fg
|
||||||
|
end
|
||||||
|
|
||||||
|
def bg_class
|
||||||
|
"bg#{bg}" if bg
|
||||||
|
end
|
||||||
|
|
||||||
|
def bold_class
|
||||||
|
'bold' if bold?
|
||||||
|
end
|
||||||
|
|
||||||
|
def underline_class
|
||||||
|
'underline' if underline?
|
||||||
|
end
|
||||||
|
|
||||||
|
def inverse_class
|
||||||
|
'inverse' if inverse?
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
@ -0,0 +1,15 @@
|
|||||||
|
class SnapshotFragmentPresenter < Draper::Decorator
|
||||||
|
|
||||||
|
delegate :text, :brush
|
||||||
|
|
||||||
|
def to_html
|
||||||
|
h.content_tag(:span, text, :class => css_class)
|
||||||
|
end
|
||||||
|
|
||||||
|
private
|
||||||
|
|
||||||
|
def css_class
|
||||||
|
BrushPresenter.new(brush).to_css_class
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
@ -0,0 +1,19 @@
|
|||||||
|
class SnapshotLinePresenter < Draper::Decorator
|
||||||
|
|
||||||
|
delegate :fragments
|
||||||
|
|
||||||
|
def to_html
|
||||||
|
h.content_tag(:span, fragment_strings.join.html_safe, :class => 'line')
|
||||||
|
end
|
||||||
|
|
||||||
|
private
|
||||||
|
|
||||||
|
def fragment_strings
|
||||||
|
fragments.map { |fragment| fragment_string(fragment) }
|
||||||
|
end
|
||||||
|
|
||||||
|
def fragment_string(fragment)
|
||||||
|
SnapshotFragmentPresenter.new(fragment).to_html
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
@ -0,0 +1,19 @@
|
|||||||
|
class SnapshotPresenter < Draper::Decorator
|
||||||
|
|
||||||
|
delegate :lines
|
||||||
|
|
||||||
|
def to_html
|
||||||
|
h.content_tag(:pre, line_strings.join.html_safe, :class => 'thumbnail')
|
||||||
|
end
|
||||||
|
|
||||||
|
private
|
||||||
|
|
||||||
|
def line_strings
|
||||||
|
lines.map { |line| line_string(line) }
|
||||||
|
end
|
||||||
|
|
||||||
|
def line_string(line)
|
||||||
|
SnapshotLinePresenter.new(line).to_html
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
@ -0,0 +1,57 @@
|
|||||||
|
require 'spec_helper'
|
||||||
|
|
||||||
|
describe SnapshotFragment do
|
||||||
|
describe '#==' do
|
||||||
|
let(:snapshot_fragment) { SnapshotFragment.new('foo', brush_1) }
|
||||||
|
let(:brush_1) { double('brush_1') }
|
||||||
|
let(:brush_2) { double('brush_2') }
|
||||||
|
|
||||||
|
subject { snapshot_fragment == other }
|
||||||
|
|
||||||
|
context "when fragments have the same texts and brushes" do
|
||||||
|
let(:other) { SnapshotFragment.new('foo', brush_1) }
|
||||||
|
|
||||||
|
it { should be(true) }
|
||||||
|
end
|
||||||
|
|
||||||
|
context "when fragments have different texts" do
|
||||||
|
let(:other) { SnapshotFragment.new('bar', brush_1) }
|
||||||
|
|
||||||
|
it { should be(false) }
|
||||||
|
end
|
||||||
|
|
||||||
|
context "when fragments have different brushes" do
|
||||||
|
let(:other) { SnapshotFragment.new('foo', brush_2) }
|
||||||
|
|
||||||
|
it { should be(false) }
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
describe '#crop' do
|
||||||
|
let(:snapshot_fragment) { SnapshotFragment.new('foobar', brush) }
|
||||||
|
let(:brush) { double('brush') }
|
||||||
|
|
||||||
|
context "when size is smaller than fragment's size" do
|
||||||
|
subject { snapshot_fragment.crop(3) }
|
||||||
|
|
||||||
|
it 'returns a new instance of SnapshotFragment' do
|
||||||
|
expect(subject).to be_kind_of(SnapshotFragment)
|
||||||
|
expect(subject).to_not be(snapshot_fragment)
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'trims the text to the requested size' do
|
||||||
|
expect(subject.text).to eq('foo')
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'returns SnapshotFragment with the same brush' do
|
||||||
|
expect(subject.brush).to be(brush)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
context "when size is equal or larger than the fragment's size" do
|
||||||
|
it 'returns self' do
|
||||||
|
expect(snapshot_fragment.crop(6)).to be(snapshot_fragment)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
@ -0,0 +1,60 @@
|
|||||||
|
require 'spec_helper'
|
||||||
|
|
||||||
|
describe SnapshotLine do
|
||||||
|
describe '#==' do
|
||||||
|
let(:snapshot_line) { SnapshotLine.new([:foo]) }
|
||||||
|
|
||||||
|
subject { snapshot_line == other }
|
||||||
|
|
||||||
|
context "when lines have the same fragments" do
|
||||||
|
let(:other) { SnapshotLine.new([:foo]) }
|
||||||
|
|
||||||
|
it { should be(true) }
|
||||||
|
end
|
||||||
|
|
||||||
|
context "when lines have different fragments" do
|
||||||
|
let(:other) { SnapshotLine.new([:foo, :bar]) }
|
||||||
|
|
||||||
|
it { should be(false) }
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
describe '#crop' do
|
||||||
|
let(:snapshot_line) { SnapshotLine.new(fragments) }
|
||||||
|
let(:fragments) { [fragment_1, fragment_2] }
|
||||||
|
let(:fragment_1) { double('fragment_1', :size => 2, :crop => nil) }
|
||||||
|
let(:fragment_2) { double('fragment_2', :size => 3,
|
||||||
|
:crop => cropped_fragment_2) }
|
||||||
|
let(:fragment_3) { double('fragment_3', :size => 4, :crop => nil) }
|
||||||
|
let(:cropped_fragment_2) { double('cropped_fragment_2', :size => 2) }
|
||||||
|
|
||||||
|
context "when cropping point is at the end of the first fragment" do
|
||||||
|
it 'crops none of the fragments' do
|
||||||
|
snapshot_line.crop(2)
|
||||||
|
|
||||||
|
expect(fragment_1).to_not have_received(:crop)
|
||||||
|
expect(fragment_2).to_not have_received(:crop)
|
||||||
|
expect(fragment_3).to_not have_received(:crop)
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'returns a new SnapshotLine with only the first fragment' do
|
||||||
|
expect(snapshot_line.crop(2)).to eq(SnapshotLine.new([fragment_1]))
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
context "when cropping point is inside of the second fragment" do
|
||||||
|
it 'crops only the second fragment' do
|
||||||
|
snapshot_line.crop(4)
|
||||||
|
|
||||||
|
expect(fragment_1).to_not have_received(:crop)
|
||||||
|
expect(fragment_2).to have_received(:crop).with(2)
|
||||||
|
expect(fragment_3).to_not have_received(:crop)
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'returns a new SnapshotLine with first two fragments cropped' do
|
||||||
|
expect(snapshot_line.crop(4)).
|
||||||
|
to eq(SnapshotLine.new([fragment_1, cropped_fragment_2]))
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
@ -0,0 +1,91 @@
|
|||||||
|
require 'spec_helper'
|
||||||
|
|
||||||
|
describe BrushPresenter do
|
||||||
|
let(:brush_presenter) { BrushPresenter.new(brush) }
|
||||||
|
let(:brush) { double('brush', :fg => nil, :bg => nil, :bold? => false,
|
||||||
|
:underline? => false, :inverse? => false) }
|
||||||
|
|
||||||
|
describe '#to_css_class' do
|
||||||
|
subject { brush_presenter.to_css_class }
|
||||||
|
|
||||||
|
context "when brush is a default one" do
|
||||||
|
before do
|
||||||
|
allow(brush).to receive(:default?) { true }
|
||||||
|
end
|
||||||
|
|
||||||
|
it { should be(nil) }
|
||||||
|
end
|
||||||
|
|
||||||
|
context "when brush is not a default one" do
|
||||||
|
before do
|
||||||
|
allow(brush).to receive(:default?) { false }
|
||||||
|
end
|
||||||
|
|
||||||
|
context "when fg is default" do
|
||||||
|
before do
|
||||||
|
allow(brush).to receive(:fg) { nil }
|
||||||
|
end
|
||||||
|
|
||||||
|
it { should_not match(/\bfg/) }
|
||||||
|
end
|
||||||
|
|
||||||
|
context "when fg is non-default" do
|
||||||
|
before do
|
||||||
|
allow(brush).to receive(:fg) { 1 }
|
||||||
|
end
|
||||||
|
|
||||||
|
it { should match(/\bfg1\b/) }
|
||||||
|
end
|
||||||
|
|
||||||
|
context "when bg is default" do
|
||||||
|
before do
|
||||||
|
allow(brush).to receive(:bg) { nil }
|
||||||
|
end
|
||||||
|
|
||||||
|
it { should_not match(/\bbg/) }
|
||||||
|
end
|
||||||
|
|
||||||
|
context "when bg is non-default" do
|
||||||
|
before do
|
||||||
|
allow(brush).to receive(:bg) { 2 }
|
||||||
|
end
|
||||||
|
|
||||||
|
it { should match(/\bbg2\b/) }
|
||||||
|
end
|
||||||
|
|
||||||
|
context "when both fg and bg are non-default" do
|
||||||
|
before do
|
||||||
|
allow(brush).to receive(:fg) { 1 }
|
||||||
|
allow(brush).to receive(:bg) { 2 }
|
||||||
|
end
|
||||||
|
|
||||||
|
it { should match(/\bfg1\b/) }
|
||||||
|
it { should match(/\bbg2\b/) }
|
||||||
|
end
|
||||||
|
|
||||||
|
context "when it's bold" do
|
||||||
|
before do
|
||||||
|
allow(brush).to receive(:bold?) { true }
|
||||||
|
end
|
||||||
|
|
||||||
|
it { should match(/\bbold\b/) }
|
||||||
|
end
|
||||||
|
|
||||||
|
context "when it's underline" do
|
||||||
|
before do
|
||||||
|
allow(brush).to receive(:underline?) { true }
|
||||||
|
end
|
||||||
|
|
||||||
|
it { should match(/\bunderline\b/) }
|
||||||
|
end
|
||||||
|
|
||||||
|
context "when it's inverse" do
|
||||||
|
before do
|
||||||
|
allow(brush).to receive(:inverse?) { true }
|
||||||
|
end
|
||||||
|
|
||||||
|
it { should match(/\binverse\b/) }
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
@ -0,0 +1,27 @@
|
|||||||
|
require 'spec_helper'
|
||||||
|
|
||||||
|
describe SnapshotFragmentPresenter do
|
||||||
|
let(:snapshot_fragment_presenter) { SnapshotFragmentPresenter.new(snapshot_fragment) }
|
||||||
|
let(:snapshot_fragment) { SnapshotFragment.new('foo > bar', brush) }
|
||||||
|
let(:brush) { double('brush') }
|
||||||
|
let(:brush_presenter) { double('brush_presenter', :to_css_class => css_class) }
|
||||||
|
let(:css_class) { 'qux' }
|
||||||
|
|
||||||
|
describe '#to_html' do
|
||||||
|
subject { snapshot_fragment_presenter.to_html }
|
||||||
|
|
||||||
|
before do
|
||||||
|
allow(BrushPresenter).to receive(:new).with(brush).
|
||||||
|
and_return(brush_presenter)
|
||||||
|
end
|
||||||
|
|
||||||
|
it { should be_kind_of(ActiveSupport::SafeBuffer) }
|
||||||
|
it { should eq('<span class="qux">foo > bar</span>') }
|
||||||
|
|
||||||
|
context "when css class is nil" do
|
||||||
|
let(:css_class) { nil }
|
||||||
|
|
||||||
|
it { should eq('<span>foo > bar</span>') }
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
@ -0,0 +1,24 @@
|
|||||||
|
require 'spec_helper'
|
||||||
|
|
||||||
|
describe SnapshotLinePresenter do
|
||||||
|
let(:snapshot_line_presenter) { SnapshotLinePresenter.new(snapshot_line) }
|
||||||
|
let(:snapshot_line) { SnapshotLine.new([fragment_1, fragment_2]) }
|
||||||
|
let(:fragment_1) { double('fragment_1') }
|
||||||
|
let(:fragment_2) { double('fragment_2') }
|
||||||
|
let(:fragment_1_presenter) { double(:to_html => '<fragment_1>') }
|
||||||
|
let(:fragment_2_presenter) { double(:to_html => '<fragment_2>') }
|
||||||
|
|
||||||
|
describe '#to_html' do
|
||||||
|
subject { snapshot_line_presenter.to_html }
|
||||||
|
|
||||||
|
before do
|
||||||
|
allow(SnapshotFragmentPresenter).to receive(:new).with(fragment_1).
|
||||||
|
and_return(fragment_1_presenter)
|
||||||
|
allow(SnapshotFragmentPresenter).to receive(:new).with(fragment_2).
|
||||||
|
and_return(fragment_2_presenter)
|
||||||
|
end
|
||||||
|
|
||||||
|
it { should be_kind_of(ActiveSupport::SafeBuffer) }
|
||||||
|
it { should eq('<span class="line"><fragment_1><fragment_2></span>') }
|
||||||
|
end
|
||||||
|
end
|
@ -0,0 +1,24 @@
|
|||||||
|
require 'spec_helper'
|
||||||
|
|
||||||
|
describe SnapshotPresenter do
|
||||||
|
let(:snapshot_presenter) { SnapshotPresenter.new(snapshot) }
|
||||||
|
let(:snapshot) { Snapshot.new([line_1, line_2]) }
|
||||||
|
let(:line_1) { double('line_1') }
|
||||||
|
let(:line_2) { double('line_2') }
|
||||||
|
let(:line_1_presenter) { double(:to_html => '<line_1>') }
|
||||||
|
let(:line_2_presenter) { double(:to_html => '<line_2>') }
|
||||||
|
|
||||||
|
describe '#to_html' do
|
||||||
|
subject { snapshot_presenter.to_html }
|
||||||
|
|
||||||
|
before do
|
||||||
|
allow(SnapshotLinePresenter).to receive(:new).with(line_1).
|
||||||
|
and_return(line_1_presenter)
|
||||||
|
allow(SnapshotLinePresenter).to receive(:new).with(line_2).
|
||||||
|
and_return(line_2_presenter)
|
||||||
|
end
|
||||||
|
|
||||||
|
it { should be_kind_of(ActiveSupport::SafeBuffer) }
|
||||||
|
it { should eq('<pre class="thumbnail"><line_1><line_2></pre>') }
|
||||||
|
end
|
||||||
|
end
|
Loading…
Reference in New Issue