markababy 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/README.txt +29 -0
- data/Rakefile +5 -0
- data/lib/markababy/rails.rb +41 -0
- data/lib/markababy.rb +67 -0
- data/markababy.gemspec +14 -0
- data/spec/markababy_rails_spec.rb +28 -0
- data/spec/markababy_spec.rb +73 -0
- data/spec/views/index.html.rb +7 -0
- metadata +75 -0
data/README.txt
ADDED
@@ -0,0 +1,29 @@
|
|
1
|
+
Markaby's little sister.
|
2
|
+
|
3
|
+
Usage is similar to Markaby, and easy to use directly from a Ruby script:
|
4
|
+
|
5
|
+
require 'markababy'
|
6
|
+
|
7
|
+
Markababy.markup do
|
8
|
+
html do
|
9
|
+
head { title 'Boats.com' }
|
10
|
+
body do
|
11
|
+
h1 'Boats.com has great deals'
|
12
|
+
ul do
|
13
|
+
li '$49 for a canoe'
|
14
|
+
li '$39 for a raft'
|
15
|
+
li '$29 for a huge boot that floats and can fit 5 people'
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
Use Markababy.capture if you want to capture the output as a string instead
|
22
|
+
of printing it to $stdout.
|
23
|
+
|
24
|
+
Some differences from Markaby:
|
25
|
+
|
26
|
+
* No auto-stringification
|
27
|
+
* No element classes or IDs
|
28
|
+
* No validation
|
29
|
+
* No XHTML
|
data/Rakefile
ADDED
@@ -0,0 +1,41 @@
|
|
1
|
+
require 'markababy'
|
2
|
+
require 'action_view'
|
3
|
+
|
4
|
+
module Markababy
|
5
|
+
class RailsTemplateContext
|
6
|
+
def initialize(controller)
|
7
|
+
@controller = controller
|
8
|
+
|
9
|
+
@ivars = @controller.instance_variables - @controller.class.new.instance_variables
|
10
|
+
end
|
11
|
+
|
12
|
+
def respond_to_missing?(sym, include_private = false)
|
13
|
+
@ivars.include?(:"@#{sym}") || @controller.respond_to?(sym)
|
14
|
+
end
|
15
|
+
|
16
|
+
def method_missing(sym, *args, &block)
|
17
|
+
if args.empty? && block.nil? && @ivars.include?(ivar = :"@#{sym}")
|
18
|
+
@controller.instance_variable_get(ivar)
|
19
|
+
elsif @controller.respond_to?(sym)
|
20
|
+
@controller.send(sym, *args, &block)
|
21
|
+
else
|
22
|
+
super sym, *args, &block
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
module RailsTemplateHandler
|
28
|
+
def self.call(template)
|
29
|
+
"self.output_buffer = ''\n" +
|
30
|
+
"Markababy.capture(output: self.output_buffer, context: Markababy::RailsTemplateContext.new(self)) do\n" +
|
31
|
+
"#{template.source}\n" +
|
32
|
+
"end\n"
|
33
|
+
end
|
34
|
+
|
35
|
+
def self.extended(base)
|
36
|
+
base.register_default_template_handler :rb, self
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
ActionView::Template.extend RailsTemplateHandler
|
41
|
+
end
|
data/lib/markababy.rb
ADDED
@@ -0,0 +1,67 @@
|
|
1
|
+
require 'cgi'
|
2
|
+
|
3
|
+
module Markababy
|
4
|
+
def self.capture(options = {}, &block)
|
5
|
+
[].tap { |output| markup(options.merge(output: output), &block) }.join
|
6
|
+
end
|
7
|
+
|
8
|
+
def self.markup(options = {}, &block)
|
9
|
+
options[:escape] = CGI.method(:escapeHTML)
|
10
|
+
|
11
|
+
options[:output] = $stdout unless options.has_key?(:output)
|
12
|
+
|
13
|
+
options[:output] << "<!DOCTYPE html>\n" if options[:doctype]
|
14
|
+
|
15
|
+
Builder.new(options, &block)
|
16
|
+
end
|
17
|
+
|
18
|
+
class Builder < BasicObject
|
19
|
+
def initialize(options, &block)
|
20
|
+
@options = options
|
21
|
+
|
22
|
+
@output = @options[:output]
|
23
|
+
|
24
|
+
@escape = @options[:escape]
|
25
|
+
|
26
|
+
@context = @options[:context]
|
27
|
+
|
28
|
+
instance_eval(&block)
|
29
|
+
end
|
30
|
+
|
31
|
+
def method_missing(sym, *args, &block)
|
32
|
+
if !@context.nil? && @context.respond_to?(sym)
|
33
|
+
return @context.send(sym, *args, &block)
|
34
|
+
end
|
35
|
+
|
36
|
+
attributes, content = [], []
|
37
|
+
|
38
|
+
args.flatten.each do |arg|
|
39
|
+
if arg.respond_to?(:to_hash)
|
40
|
+
arg.to_hash.each { |k, v| attributes << ' %s="%s"' % [@escape[k.to_s], @escape[v.to_s]] }
|
41
|
+
elsif arg.respond_to?(:id2name)
|
42
|
+
attributes << ' %s' % @escape[arg.to_s]
|
43
|
+
elsif arg.respond_to?(:html_safe?) && arg.html_safe?
|
44
|
+
content << arg.to_s
|
45
|
+
else
|
46
|
+
content << @escape[arg.to_s]
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
@output << (attributes.empty? ? "<#{sym}>" : "<#{sym}#{attributes.join}>")
|
51
|
+
|
52
|
+
@output << content.join unless content.empty?
|
53
|
+
|
54
|
+
instance_eval(&block) unless block.nil?
|
55
|
+
|
56
|
+
@output << "</#{sym}>" unless content.empty? && block.nil?
|
57
|
+
end
|
58
|
+
|
59
|
+
def text(content)
|
60
|
+
if content.respond_to?(:html_safe?) && content.html_safe?
|
61
|
+
@output << content.to_s
|
62
|
+
else
|
63
|
+
@output << @escape[content.to_s]
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
data/markababy.gemspec
ADDED
@@ -0,0 +1,14 @@
|
|
1
|
+
Gem::Specification.new do |s|
|
2
|
+
s.name = 'markababy'
|
3
|
+
s.version = '1.0.0'
|
4
|
+
s.platform = Gem::Platform::RUBY
|
5
|
+
s.authors = ['Tim Craft']
|
6
|
+
s.email = ['mail@timcraft.com']
|
7
|
+
s.homepage = 'http://github.com/timcraft/markababy'
|
8
|
+
s.description = 'Markaby\'s little sister'
|
9
|
+
s.summary = 'See description'
|
10
|
+
s.files = Dir.glob('{lib,spec}/**/*') + %w(README.txt Rakefile markababy.gemspec)
|
11
|
+
s.add_development_dependency('activesupport', ['>= 3.0.3'])
|
12
|
+
s.add_development_dependency('actionpack', ['>= 3.0.3'])
|
13
|
+
s.require_path = 'lib'
|
14
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
require 'minitest/autorun'
|
2
|
+
require 'abstract_controller'
|
3
|
+
require 'markababy'
|
4
|
+
require 'markababy/rails'
|
5
|
+
|
6
|
+
class DummyController < AbstractController::Base
|
7
|
+
# cf. http://amberbit.com/blog/render-views-partials-outside-controllers-rails-3
|
8
|
+
|
9
|
+
include AbstractController::Rendering
|
10
|
+
include AbstractController::Layouts
|
11
|
+
include AbstractController::Helpers
|
12
|
+
|
13
|
+
self.view_paths = 'spec/views'
|
14
|
+
|
15
|
+
def index
|
16
|
+
@message = 'Controller says hello!'
|
17
|
+
|
18
|
+
render template: 'index'
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
describe DummyController do
|
23
|
+
it 'should return the correct markup' do
|
24
|
+
output = '<html><head><title>Controller says hello!</title><p>12,345,678</p></head></html>'
|
25
|
+
|
26
|
+
DummyController.new.index.must_equal output
|
27
|
+
end
|
28
|
+
end
|
@@ -0,0 +1,73 @@
|
|
1
|
+
require 'minitest/autorun'
|
2
|
+
require 'markababy'
|
3
|
+
require 'active_support/core_ext/string/output_safety'
|
4
|
+
|
5
|
+
class ExampleContext
|
6
|
+
def baconize(word)
|
7
|
+
"#{word} bacon!"
|
8
|
+
end
|
9
|
+
end
|
10
|
+
|
11
|
+
describe Markababy do
|
12
|
+
it 'should render tags without attributes or content correctly' do
|
13
|
+
Markababy.capture { br }.must_equal '<br>'
|
14
|
+
end
|
15
|
+
|
16
|
+
it 'should render tags with content correctly' do
|
17
|
+
Markababy.capture { title 'Untitled' }.must_equal '<title>Untitled</title>'
|
18
|
+
end
|
19
|
+
|
20
|
+
it 'should escape content correctly' do
|
21
|
+
Markababy.capture { h1 'Apples & Oranges' }.must_equal '<h1>Apples & Oranges</h1>'
|
22
|
+
end
|
23
|
+
|
24
|
+
it 'should render tags with an attribute hash correctly' do
|
25
|
+
Markababy.capture { input type: :text, size: 40 }.must_equal '<input type="text" size="40">'
|
26
|
+
end
|
27
|
+
|
28
|
+
it 'should render tags with an attribute array correctly' do
|
29
|
+
Markababy.capture { input [{type: :text}, :disabled] }.must_equal '<input type="text" disabled>'
|
30
|
+
end
|
31
|
+
|
32
|
+
it 'should render tags with attributes and content correctly' do
|
33
|
+
Markababy.capture { div 'O hai', class: 'name' }.must_equal '<div class="name">O hai</div>'
|
34
|
+
end
|
35
|
+
|
36
|
+
it 'should render nested tags correctly' do
|
37
|
+
Markababy.capture { h1 { span 'Chunky bacon!' } }.must_equal '<h1><span>Chunky bacon!</span></h1>'
|
38
|
+
end
|
39
|
+
|
40
|
+
it 'should allow output target to be specified' do
|
41
|
+
output = []
|
42
|
+
|
43
|
+
Markababy.markup(output: output) { hr }
|
44
|
+
|
45
|
+
output.join.must_equal '<hr>'
|
46
|
+
end
|
47
|
+
|
48
|
+
it 'should allow context for method lookup to be specified' do
|
49
|
+
output = Markababy.capture(context: ExampleContext.new) { h1 baconize('Super chunky') }
|
50
|
+
|
51
|
+
output.must_equal '<h1>Super chunky bacon!</h1>'
|
52
|
+
end
|
53
|
+
|
54
|
+
it 'should provide a method for rendering text content' do
|
55
|
+
output = Markababy.capture { h1 { text 'Hello '; strong 'World' } }
|
56
|
+
|
57
|
+
output.must_equal '<h1>Hello <strong>World</strong></h1>'
|
58
|
+
end
|
59
|
+
|
60
|
+
it 'should respect the html_safe? method' do
|
61
|
+
Markababy.capture { text 'Hello World'.html_safe }.must_equal 'Hello World'
|
62
|
+
|
63
|
+
output = Markababy.capture { h1 'Hello <strong>World</strong>'.html_safe }
|
64
|
+
|
65
|
+
output.must_equal '<h1>Hello <strong>World</strong></h1>'
|
66
|
+
end
|
67
|
+
|
68
|
+
it 'should provide an option for including a doctype declaration' do
|
69
|
+
output = Markababy.capture(doctype: true) { html { body { p 'INSERT CONTENT HERE' } } }
|
70
|
+
|
71
|
+
output.must_equal "<!DOCTYPE html>\n<html><body><p>INSERT CONTENT HERE</p></body></html>"
|
72
|
+
end
|
73
|
+
end
|
metadata
ADDED
@@ -0,0 +1,75 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: markababy
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 1.0.0
|
5
|
+
prerelease:
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- Tim Craft
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
date: 2011-10-11 00:00:00.000000000Z
|
13
|
+
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
15
|
+
name: activesupport
|
16
|
+
requirement: &10149360 !ruby/object:Gem::Requirement
|
17
|
+
none: false
|
18
|
+
requirements:
|
19
|
+
- - ! '>='
|
20
|
+
- !ruby/object:Gem::Version
|
21
|
+
version: 3.0.3
|
22
|
+
type: :development
|
23
|
+
prerelease: false
|
24
|
+
version_requirements: *10149360
|
25
|
+
- !ruby/object:Gem::Dependency
|
26
|
+
name: actionpack
|
27
|
+
requirement: &10149030 !ruby/object:Gem::Requirement
|
28
|
+
none: false
|
29
|
+
requirements:
|
30
|
+
- - ! '>='
|
31
|
+
- !ruby/object:Gem::Version
|
32
|
+
version: 3.0.3
|
33
|
+
type: :development
|
34
|
+
prerelease: false
|
35
|
+
version_requirements: *10149030
|
36
|
+
description: Markaby's little sister
|
37
|
+
email:
|
38
|
+
- mail@timcraft.com
|
39
|
+
executables: []
|
40
|
+
extensions: []
|
41
|
+
extra_rdoc_files: []
|
42
|
+
files:
|
43
|
+
- lib/markababy/rails.rb
|
44
|
+
- lib/markababy.rb
|
45
|
+
- spec/markababy_rails_spec.rb
|
46
|
+
- spec/markababy_spec.rb
|
47
|
+
- spec/views/index.html.rb
|
48
|
+
- README.txt
|
49
|
+
- Rakefile
|
50
|
+
- markababy.gemspec
|
51
|
+
homepage: http://github.com/timcraft/markababy
|
52
|
+
licenses: []
|
53
|
+
post_install_message:
|
54
|
+
rdoc_options: []
|
55
|
+
require_paths:
|
56
|
+
- lib
|
57
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
58
|
+
none: false
|
59
|
+
requirements:
|
60
|
+
- - ! '>='
|
61
|
+
- !ruby/object:Gem::Version
|
62
|
+
version: '0'
|
63
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
64
|
+
none: false
|
65
|
+
requirements:
|
66
|
+
- - ! '>='
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '0'
|
69
|
+
requirements: []
|
70
|
+
rubyforge_project:
|
71
|
+
rubygems_version: 1.8.10
|
72
|
+
signing_key:
|
73
|
+
specification_version: 3
|
74
|
+
summary: See description
|
75
|
+
test_files: []
|