erbside 0.1.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/HISTORY +11 -0
- data/LICENSE +206 -0
- data/PROFILE +27 -0
- data/README +88 -0
- data/VERSION +1 -0
- data/bin/erbside +3 -0
- data/lib/erbside.rb +57 -0
- data/lib/erbside/context.rb +46 -0
- data/lib/erbside/inline.rb +249 -0
- data/lib/erbside/inline/bash.rb +33 -0
- data/lib/erbside/inline/cpp.rb +32 -0
- data/lib/erbside/inline/css.rb +34 -0
- data/lib/erbside/inline/js.rb +34 -0
- data/lib/erbside/inline/ruby.rb +34 -0
- data/lib/erbside/inline/sgml.rb +135 -0
- data/lib/erbside/metadata.rb +122 -0
- data/lib/erbside/runner.rb +128 -0
- data/lib/plugins/syckle/erbside.rb +45 -0
- data/test/functional/applique/env.rb +33 -0
- data/test/functional/bash.rdoc +57 -0
- data/test/functional/cli.rdoc +14 -0
- data/test/functional/cpp.rdoc +50 -0
- data/test/functional/css.rdoc +53 -0
- data/test/functional/javascript.rdoc +52 -0
- data/test/functional/ruby.rdoc +57 -0
- data/test/functional/sgml.rdoc +61 -0
- data/test/unit/fixture/inline.rb +29 -0
- data/test/unit/fixture/inline_complex.rb +0 -0
- data/test/unit/inline_test.rb +14 -0
- metadata +111 -0
@@ -0,0 +1,122 @@
|
|
1
|
+
module Erbside
|
2
|
+
|
3
|
+
# Metadata belongs to the project being scaffold.
|
4
|
+
#
|
5
|
+
# TODO: Support POM::Metadata
|
6
|
+
#
|
7
|
+
class Metadata
|
8
|
+
|
9
|
+
#require 'facets/ostruct'
|
10
|
+
|
11
|
+
begin
|
12
|
+
require 'pom'
|
13
|
+
rescue LoadError
|
14
|
+
end
|
15
|
+
|
16
|
+
# Project root pathname.
|
17
|
+
attr :root
|
18
|
+
|
19
|
+
#
|
20
|
+
def initialize(root=nil)
|
21
|
+
@root = self.class.root(root) || Dir.pwd
|
22
|
+
|
23
|
+
if defined?(POM)
|
24
|
+
@pom = POM::Metadata.new(@root)
|
25
|
+
else
|
26
|
+
@pom = nil
|
27
|
+
end
|
28
|
+
|
29
|
+
@cache = {} #OpenStruct.new
|
30
|
+
|
31
|
+
load_metadata # TODO: when pom supports arbitrary metadata, merge @pom and @cache into same variable.
|
32
|
+
end
|
33
|
+
|
34
|
+
#
|
35
|
+
def method_missing(s, *a)
|
36
|
+
return super unless a.empty?
|
37
|
+
if @pom
|
38
|
+
begin
|
39
|
+
@pom.__send__(s, *a)
|
40
|
+
rescue
|
41
|
+
@cache.key?(s.to_s) ? @cache[s.to_s] : nil
|
42
|
+
end
|
43
|
+
else
|
44
|
+
@cache.key?(s.to_s) ? @cache[s.to_s] : nil
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
# Provide metadata to hash. Some (stencil) template systems
|
49
|
+
# need the data in hash form.
|
50
|
+
|
51
|
+
def to_h
|
52
|
+
if @pom
|
53
|
+
@pom.to_h
|
54
|
+
else
|
55
|
+
@cache
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
private
|
60
|
+
|
61
|
+
# Load metadata. This serves as the fallback if POM is not used.
|
62
|
+
|
63
|
+
def load_metadata
|
64
|
+
Dir[File.join(metadir, '*')].each do |f|
|
65
|
+
val = File.read(f).strip
|
66
|
+
val = YAML.load(val) if val =~ /\A---/
|
67
|
+
@cache[File.basename(f)] = val
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
# What is project root's metadirectory?
|
72
|
+
|
73
|
+
def metadir
|
74
|
+
@metadir ||= Dir[File.join(root, '{.meta,meta}/')].first || '.meta/'
|
75
|
+
end
|
76
|
+
|
77
|
+
#def load_value(name)
|
78
|
+
# file = File.join(metadir, name)
|
79
|
+
# file = Dir[file].first
|
80
|
+
# if file && File.file?(file)
|
81
|
+
# #return erb(file).strip
|
82
|
+
# return File.read(file).strip
|
83
|
+
# end
|
84
|
+
#end
|
85
|
+
|
86
|
+
# Root directory is indicated by the presence of a +meta/+ directory,
|
87
|
+
# or +.meta/+ hidden directory.
|
88
|
+
|
89
|
+
ROOT_INDICATORS = [ '{.meta,meta}/' ]
|
90
|
+
|
91
|
+
# Locate the project's root directory. This is determined
|
92
|
+
# by ascending up the directory tree from the current position
|
93
|
+
# until the ROOT_INDICATORS is matched. Returns +nil+ if not found.
|
94
|
+
|
95
|
+
def self.root(local=Dir.pwd)
|
96
|
+
local ||= Dir.pwd
|
97
|
+
Dir.chdir(local) do
|
98
|
+
dir = nil
|
99
|
+
ROOT_INDICATORS.find do |i|
|
100
|
+
dir = locate_root_at(i)
|
101
|
+
end
|
102
|
+
dir ? Pathname.new(File.dirname(dir)) : nil
|
103
|
+
end
|
104
|
+
end
|
105
|
+
|
106
|
+
#
|
107
|
+
def self.locate_root_at(indicator)
|
108
|
+
root = nil
|
109
|
+
dir = Dir.pwd
|
110
|
+
while !root && dir != '/'
|
111
|
+
find = File.join(dir, indicator)
|
112
|
+
root = Dir.glob(find, File::FNM_CASEFOLD).first
|
113
|
+
#break if root
|
114
|
+
dir = File.dirname(dir)
|
115
|
+
end
|
116
|
+
root ? Pathname.new(root) : nil
|
117
|
+
end
|
118
|
+
|
119
|
+
end
|
120
|
+
|
121
|
+
end
|
122
|
+
|
@@ -0,0 +1,128 @@
|
|
1
|
+
module Erbside
|
2
|
+
|
3
|
+
# = Runner
|
4
|
+
#
|
5
|
+
class Runner
|
6
|
+
|
7
|
+
require 'erbside/inline'
|
8
|
+
require 'erbside/metadata'
|
9
|
+
|
10
|
+
require 'facets/kernel/ask'
|
11
|
+
require 'facets/string/tabto'
|
12
|
+
|
13
|
+
|
14
|
+
# A T T R I B U T E S
|
15
|
+
|
16
|
+
attr_accessor :files
|
17
|
+
|
18
|
+
attr_accessor :force
|
19
|
+
|
20
|
+
attr_accessor :skip
|
21
|
+
|
22
|
+
# The +output+ can be any object that responds to #<<.
|
23
|
+
attr_accessor :output
|
24
|
+
|
25
|
+
#attr_accessor :delete
|
26
|
+
|
27
|
+
|
28
|
+
# I N I T I A L I Z E
|
29
|
+
|
30
|
+
#
|
31
|
+
def initialize(files, options)
|
32
|
+
files = files || Dir["**/*#{ext_glob}"]
|
33
|
+
files = files.map do |file|
|
34
|
+
if File.directory?(file)
|
35
|
+
collect_usable_files(file)
|
36
|
+
else
|
37
|
+
file
|
38
|
+
end
|
39
|
+
end.flatten
|
40
|
+
@files = files
|
41
|
+
|
42
|
+
@force = options[:force]
|
43
|
+
@skip = options[:skip]
|
44
|
+
@output = options[:output]
|
45
|
+
#@delete = options[:delete]
|
46
|
+
end
|
47
|
+
|
48
|
+
#
|
49
|
+
def collect_usable_files(dir)
|
50
|
+
Dir[File.join(dir,"**/*#{ext_glob}")]
|
51
|
+
end
|
52
|
+
|
53
|
+
#def delete? ; @delete ; end
|
54
|
+
def force? ; @force ; end
|
55
|
+
def skip? ; @skip ; end
|
56
|
+
|
57
|
+
def debug? ; $DEBUG ; end
|
58
|
+
def trial? ; $TRIAL ; end
|
59
|
+
|
60
|
+
#
|
61
|
+
def render
|
62
|
+
files.each do |file|
|
63
|
+
render_file(file)
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
# Search through a file for inline templates, render and output.
|
68
|
+
def render_file(file)
|
69
|
+
parser = Inline.factory(file)
|
70
|
+
|
71
|
+
if !parser
|
72
|
+
puts " unrecognized #{file}" if $DEBUG || $TRIAL
|
73
|
+
return
|
74
|
+
end
|
75
|
+
|
76
|
+
template = parser.new(file)
|
77
|
+
|
78
|
+
if template.exist? && skip?
|
79
|
+
puts " #{template.relative_output} skipped"
|
80
|
+
else
|
81
|
+
result = template.render
|
82
|
+
if output
|
83
|
+
output << (result + "\n")
|
84
|
+
else
|
85
|
+
save(template, result)
|
86
|
+
end
|
87
|
+
end
|
88
|
+
end
|
89
|
+
|
90
|
+
#
|
91
|
+
def save(template, result)
|
92
|
+
name = template.relative_output
|
93
|
+
save = false
|
94
|
+
if trial?
|
95
|
+
puts " #{name}"
|
96
|
+
else
|
97
|
+
if template.exist?
|
98
|
+
if !template.changed?
|
99
|
+
puts " unchanged #{name}"
|
100
|
+
elsif !force?
|
101
|
+
case ask(" overwrite #{name}? ")
|
102
|
+
when 'y', 'yes'
|
103
|
+
save = true
|
104
|
+
end
|
105
|
+
else
|
106
|
+
save = true
|
107
|
+
end
|
108
|
+
else
|
109
|
+
save = true
|
110
|
+
end
|
111
|
+
end
|
112
|
+
if save
|
113
|
+
template.save
|
114
|
+
puts " written #{name}"
|
115
|
+
end
|
116
|
+
end
|
117
|
+
|
118
|
+
|
119
|
+
private
|
120
|
+
|
121
|
+
#
|
122
|
+
def ext_glob
|
123
|
+
'{' + Inline.extension_list.join(',') + '}'
|
124
|
+
end
|
125
|
+
|
126
|
+
end
|
127
|
+
|
128
|
+
end
|
@@ -0,0 +1,45 @@
|
|
1
|
+
module Syckle::Plugins
|
2
|
+
|
3
|
+
# = Erbside Generation
|
4
|
+
#
|
5
|
+
class Erbside < Service
|
6
|
+
|
7
|
+
cycle :main, :generate
|
8
|
+
cycle :site, :generate
|
9
|
+
|
10
|
+
# Make automatic?
|
11
|
+
#autorun do
|
12
|
+
# ...
|
13
|
+
#end
|
14
|
+
|
15
|
+
available do |project|
|
16
|
+
begin
|
17
|
+
require 'erbside'
|
18
|
+
true
|
19
|
+
rescue LoadError
|
20
|
+
false
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
#
|
25
|
+
#def safe?; @safe; end
|
26
|
+
|
27
|
+
#
|
28
|
+
def generate(options={})
|
29
|
+
options ||= {}
|
30
|
+
|
31
|
+
dir = nil # defaults to curent directory
|
32
|
+
|
33
|
+
options[:trial] = trial?
|
34
|
+
options[:debug] = debug?
|
35
|
+
options[:quiet] = quiet?
|
36
|
+
options[:force] = force?
|
37
|
+
|
38
|
+
tiller = Erbside::Runner.new(dir, options)
|
39
|
+
tiller.till
|
40
|
+
end
|
41
|
+
|
42
|
+
end
|
43
|
+
|
44
|
+
end
|
45
|
+
|
@@ -0,0 +1,33 @@
|
|
1
|
+
#require 'tmpdir'
|
2
|
+
require 'erbside'
|
3
|
+
|
4
|
+
When "Given a file named '(((.*?)))'" do |name, text|
|
5
|
+
File.open(name, 'w+'){ |f| f << text }
|
6
|
+
end
|
7
|
+
|
8
|
+
When "Rendering via the commandline" do |text|
|
9
|
+
#@result = Erbside.cli('-o', 'example.rb')
|
10
|
+
text.sub!(/^\$\s*/, '')
|
11
|
+
@result = `#{text}`
|
12
|
+
end
|
13
|
+
|
14
|
+
When "result will be" do |text|
|
15
|
+
text.strip.assert == @result.strip
|
16
|
+
end
|
17
|
+
|
18
|
+
When "The rendered result of '(((.*?)))' will be" do |file, text|
|
19
|
+
result = ""
|
20
|
+
runner = Erbside::Runner.new([file], :output=>result)
|
21
|
+
runner.render
|
22
|
+
|
23
|
+
text.strip.assert == result.strip
|
24
|
+
end
|
25
|
+
|
26
|
+
|
27
|
+
# out = File.join(@tmpdir, "fixture/inline.rb")
|
28
|
+
# system "till -f #{out}"
|
29
|
+
# expect = File.read('test/features/proofs/inline.rb')
|
30
|
+
# result = File.read(out)
|
31
|
+
#
|
32
|
+
# assert_equal(expect, result)
|
33
|
+
|
@@ -0,0 +1,57 @@
|
|
1
|
+
== Bash
|
2
|
+
|
3
|
+
=== Sideline Rendering
|
4
|
+
|
5
|
+
Given a file named 'example.sh' containing:
|
6
|
+
|
7
|
+
# ordinary comment
|
8
|
+
VERSION = "?" # :erb: VERSION = "<%= 1+1 %>"
|
9
|
+
|
10
|
+
The rendered result of 'example.sh' will be:
|
11
|
+
|
12
|
+
# ordinary comment
|
13
|
+
VERSION = "2" # :erb: VERSION = "<%= 1+1 %>"
|
14
|
+
|
15
|
+
=== Sideline Rendering with First Match Marker
|
16
|
+
|
17
|
+
Given a file named 'example.sh' containing:
|
18
|
+
|
19
|
+
# Script generated 200X #:erb: ^generated <%= 2009 %>
|
20
|
+
|
21
|
+
The rendered result of 'example.sh' will be:
|
22
|
+
|
23
|
+
# Script generated 2009 #:erb: ^generated <%= 2009 %>
|
24
|
+
|
25
|
+
Notice in this case we rendered a comment.
|
26
|
+
|
27
|
+
=== Multiline Rendering
|
28
|
+
|
29
|
+
Given a file named 'example.sh' containing:
|
30
|
+
|
31
|
+
#:erb+1: <%= %w{z y x}.sort.join("\n") %>
|
32
|
+
blah blah blah
|
33
|
+
|
34
|
+
The rendered result of 'example.sh' will be:
|
35
|
+
|
36
|
+
#:erb+3: <%= %w{z y x}.sort.join("\n") %>
|
37
|
+
x
|
38
|
+
y
|
39
|
+
z
|
40
|
+
|
41
|
+
=== Block Rendering
|
42
|
+
|
43
|
+
Given a file named 'example.sh' containing:
|
44
|
+
|
45
|
+
#=begin :erb+0:
|
46
|
+
<%= %w{a b c}.map{ |x| "#{x}!" }.join("\n") %>
|
47
|
+
#=end
|
48
|
+
|
49
|
+
The rendered result of 'example.sh' will be:
|
50
|
+
|
51
|
+
#=begin :erb+3:
|
52
|
+
<%= %w{a b c}.map{ |x| "#{x}!" }.join("\n") %>
|
53
|
+
#=end
|
54
|
+
a!
|
55
|
+
b!
|
56
|
+
c!
|
57
|
+
|
@@ -0,0 +1,50 @@
|
|
1
|
+
== C/C++
|
2
|
+
|
3
|
+
=== Sideline Example
|
4
|
+
|
5
|
+
Sideline example, where the erb comment is to the side of the
|
6
|
+
text it will replace. Given a file named 'example.c' containing:
|
7
|
+
|
8
|
+
version = "?"; // :erb: version = "<%= 1+1 %>";
|
9
|
+
|
10
|
+
The rendered result of 'example.c' will be:
|
11
|
+
|
12
|
+
version = "2"; // :erb: version = "<%= 1+1 %>";
|
13
|
+
|
14
|
+
=== Multiline Example
|
15
|
+
|
16
|
+
Multi-line example, where the erb comment replaces multiple lines but
|
17
|
+
is defined by a single line. Given a file named 'example.c' containing:
|
18
|
+
|
19
|
+
void main() {
|
20
|
+
//:erb+1: <%= %w{z(); y(); x();}.sort.join("\n").indent(2) %>
|
21
|
+
will be replaced
|
22
|
+
}
|
23
|
+
|
24
|
+
The rendered result of 'example.c' will be:
|
25
|
+
|
26
|
+
void main() {
|
27
|
+
//:erb+3: <%= %w{z(); y(); x();}.sort.join("\n").indent(2) %>
|
28
|
+
x();
|
29
|
+
y();
|
30
|
+
z();
|
31
|
+
}
|
32
|
+
|
33
|
+
=== Block Example
|
34
|
+
|
35
|
+
Block example, where the ERB comment replaces multiple lines and is
|
36
|
+
defined by a block comment. Given a file named 'example.c' containing:
|
37
|
+
|
38
|
+
/* :erb+0:
|
39
|
+
<%= %w{a b c}.map{ |e| "\#include <#{e}.h>" }.join("\n") %>
|
40
|
+
*/
|
41
|
+
|
42
|
+
The rendered result of 'example.c' will be:
|
43
|
+
|
44
|
+
/* :erb+3:
|
45
|
+
<%= %w{a b c}.map{ |e| "\#include <#{e}.h>" }.join("\n") %>
|
46
|
+
*/
|
47
|
+
#include <a.h>
|
48
|
+
#include <b.h>
|
49
|
+
#include <c.h>
|
50
|
+
|