templette 0.3.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/bin/templette +25 -0
- data/bin/templette.cmd +1 -0
- data/files/Capfile +1 -0
- data/files/Rakefile +5 -0
- data/files/default_helper.rb +11 -0
- data/files/deploy.rb +37 -0
- data/lib/file_generator.rb +33 -0
- data/lib/tasks/templette_tasks.rb +47 -0
- data/lib/templette.rb +5 -0
- data/lib/templette/data_accessors.rb +40 -0
- data/lib/templette/errors.rb +20 -0
- data/lib/templette/generator.rb +39 -0
- data/lib/templette/method_collector.rb +28 -0
- data/lib/templette/page.rb +88 -0
- data/lib/templette/template.rb +36 -0
- metadata +67 -0
data/bin/templette
ADDED
@@ -0,0 +1,25 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
#
|
3
|
+
|
4
|
+
usage = <<USAGE
|
5
|
+
Generate the templette framework.
|
6
|
+
Usage: templette <directory>
|
7
|
+
--help gets you this help message... Helpful!
|
8
|
+
USAGE
|
9
|
+
|
10
|
+
require 'fileutils'
|
11
|
+
|
12
|
+
new_dir = ARGV.first
|
13
|
+
|
14
|
+
if new_dir.nil? || new_dir.empty?
|
15
|
+
puts usage
|
16
|
+
exit(0)
|
17
|
+
end
|
18
|
+
|
19
|
+
FileUtils.mkdir(new_dir) unless File.exists?(new_dir)
|
20
|
+
%w{/pages /templates /helpers /resources}.each do |dir|
|
21
|
+
FileUtils.mkdir(new_dir + dir) unless File.exists?(new_dir + dir)
|
22
|
+
end
|
23
|
+
|
24
|
+
FileUtils.cp(File.dirname(__FILE__) + '/../files/Rakefile', new_dir + '/Rakefile')
|
25
|
+
FileUtils.cp(File.dirname(__FILE__) + '/../files/default_helper.rb', new_dir + '/helpers/default_helper.rb')
|
data/bin/templette.cmd
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
@ruby "c:/ruby/bin/templette" %*
|
data/files/Capfile
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
load 'deploy'
|
data/files/Rakefile
ADDED
data/files/deploy.rb
ADDED
@@ -0,0 +1,37 @@
|
|
1
|
+
set :package_name, 'package'
|
2
|
+
set :staging_path, ''
|
3
|
+
set :user, "username"
|
4
|
+
|
5
|
+
task :staging do
|
6
|
+
role :web, 'staging.example.com'
|
7
|
+
set :deploy_path, 'public_html/staging_path'
|
8
|
+
end
|
9
|
+
|
10
|
+
task :production do
|
11
|
+
role :web, 'example.com'
|
12
|
+
set :deploy_path, 'public_html/path'
|
13
|
+
end
|
14
|
+
|
15
|
+
before "deploy", "deploy:package"
|
16
|
+
after "deploy", "deploy:cleanup"
|
17
|
+
|
18
|
+
namespace :deploy do
|
19
|
+
|
20
|
+
task :package do
|
21
|
+
`rake build destination=#{package_name}`
|
22
|
+
`tar -czvf #{package_name}.tar.gz #{package_name}`
|
23
|
+
end
|
24
|
+
|
25
|
+
desc "This is the main task"
|
26
|
+
task :default, :roles => [:web] do
|
27
|
+
upload "#{package_name}.tar.gz", "#{staging_path}#{package_name}.tar.gz"
|
28
|
+
run "tar -xzvf #{staging_path}#{package_name}.tar.gz"
|
29
|
+
run "rsync -r #{staging_path}#{package_name}/ #{deploy_path}"
|
30
|
+
end
|
31
|
+
|
32
|
+
task :cleanup do
|
33
|
+
run "rm -f #{staging_path}/#{package_name}"
|
34
|
+
run "rm -rf #{staging_path}#{package_name}"
|
35
|
+
`rm -rf #{package_name}.tar.gz`
|
36
|
+
end
|
37
|
+
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/templette'
|
2
|
+
module FileGenerator
|
3
|
+
|
4
|
+
class << self
|
5
|
+
|
6
|
+
# Called by rake generate:page template=<name> names="<file1 file2>"
|
7
|
+
#
|
8
|
+
# Generates empty page yaml files in /pages. Takes the methods called in the template and turns them into a yaml framework.
|
9
|
+
def page_yaml(template, names)
|
10
|
+
template = Templette::Template.new(template)
|
11
|
+
names.split(/\s+/).each do |name|
|
12
|
+
unless File.exists?("pages/#{name}.yml")
|
13
|
+
File.open("pages/#{name}.yml", 'w') {|f| f << template.to_yaml }
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
# Called by rake generate:helper name=<template_name>
|
19
|
+
#
|
20
|
+
# Generates a helper module in /helpers. A helper will be loaded if it shares the name of the template being applied.
|
21
|
+
# To load a different helper, you'll have to include it in default_helper.
|
22
|
+
def helper(name)
|
23
|
+
helper_name = name =~ /_helper\Z/ ? name : "#{name}_helper"
|
24
|
+
module_name = helper_name.split('_').map{|str| str.capitalize}.join
|
25
|
+
File.open("helpers/#{helper_name}.rb", 'w') do |f|
|
26
|
+
f << "module #{module_name}
|
27
|
+
# Add methods for the #{name} template here
|
28
|
+
end"
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
end
|
@@ -0,0 +1,47 @@
|
|
1
|
+
desc "Build an HTML project from template files"
|
2
|
+
task(:build) do
|
3
|
+
Templette::Generator.new(ENV['destination']).run
|
4
|
+
end
|
5
|
+
|
6
|
+
desc "Remove all generated files"
|
7
|
+
task :clean do
|
8
|
+
Templette::Generator.new.clean
|
9
|
+
end
|
10
|
+
|
11
|
+
namespace :cap do
|
12
|
+
|
13
|
+
desc "Install the basic capistrano recipes and Capfile"
|
14
|
+
task :install do
|
15
|
+
files_dir = File.dirname(__FILE__) + '/../../files/'
|
16
|
+
%w{Capfile deploy.rb}.each do |file|
|
17
|
+
FileUtils.cp(files_dir + file, file) unless File.exists?(file)
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
end
|
22
|
+
|
23
|
+
namespace :generate do
|
24
|
+
|
25
|
+
desc "Generate empty page files based upon template= and names="
|
26
|
+
task :page_yaml do
|
27
|
+
unless ENV['template'] && ENV['names']
|
28
|
+
puts "You must set template and names to run this task."
|
29
|
+
return
|
30
|
+
end
|
31
|
+
require 'file_generator'
|
32
|
+
FileGenerator.page_yaml(ENV['template'], ENV['names'])
|
33
|
+
end
|
34
|
+
|
35
|
+
desc "Generate an empty generator file with name=example"
|
36
|
+
task :helper do
|
37
|
+
unless ENV['name']
|
38
|
+
puts "You must enter a name for your helper."
|
39
|
+
return
|
40
|
+
end
|
41
|
+
require 'file_generator'
|
42
|
+
FileGenerator.helper(ENV['name'])
|
43
|
+
end
|
44
|
+
|
45
|
+
end
|
46
|
+
|
47
|
+
task :default => :build
|
data/lib/templette.rb
ADDED
@@ -0,0 +1,40 @@
|
|
1
|
+
module Templette
|
2
|
+
module DataAccessors
|
3
|
+
def attributes
|
4
|
+
@attributes ||= {}
|
5
|
+
end
|
6
|
+
|
7
|
+
def generate_accessors(accessors = {})
|
8
|
+
accessors.each_pair { |k,v| generate_accessor(k, v) }
|
9
|
+
end
|
10
|
+
|
11
|
+
def include_helpers(helpers)
|
12
|
+
helpers.each { |helper| add_helper(helper) }
|
13
|
+
end
|
14
|
+
|
15
|
+
def method_missing(symbol)
|
16
|
+
raise PageError.new(page, "No method '#{symbol}' defined in the yaml")
|
17
|
+
end
|
18
|
+
|
19
|
+
private
|
20
|
+
|
21
|
+
def generate_accessor(k, v)
|
22
|
+
raise TempletteError.new(page, "Method already defined: #{k}. Change your config file and stop using it!") if self.methods.include?(k.to_s)
|
23
|
+
if v.kind_of?(Hash)
|
24
|
+
v = Page::Section.new(page, v)
|
25
|
+
elsif v =~ /file:(.*)/
|
26
|
+
raise PageError.new(page, "File requested by :#{k} no found!") unless File.exists?($1)
|
27
|
+
v = File.open($1) {|f| f.read}
|
28
|
+
end
|
29
|
+
attributes[k.to_s] = v
|
30
|
+
instance_eval "def #{k.to_s}; attributes['#{k.to_s}']; end"
|
31
|
+
end
|
32
|
+
|
33
|
+
def add_helper(helper)
|
34
|
+
if File.exists?("helpers/#{helper}.rb")
|
35
|
+
require "helpers/#{helper}"
|
36
|
+
extend Object.module_eval("::#{helper.split('_').map {|str| str.capitalize}.join}", __FILE__, __LINE__)
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
module Templette
|
2
|
+
class TempletteError < Exception
|
3
|
+
|
4
|
+
def initialize(error_source, message = nil)
|
5
|
+
@error_source = error_source
|
6
|
+
@message = message
|
7
|
+
end
|
8
|
+
|
9
|
+
def to_s
|
10
|
+
"#{self.class.name.split('::').last} - #{@error_source.name}: #{@message}"
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
class TemplateError < TempletteError # :nodoc:
|
15
|
+
end
|
16
|
+
|
17
|
+
class PageError < TempletteError # :nodoc:
|
18
|
+
end
|
19
|
+
|
20
|
+
end
|
@@ -0,0 +1,39 @@
|
|
1
|
+
module Templette
|
2
|
+
class Generator
|
3
|
+
def initialize(out_dir = 'out', resources_dir = 'resources')
|
4
|
+
@out_dir = out_dir
|
5
|
+
@resources_dir = resources_dir
|
6
|
+
@errors = []
|
7
|
+
end
|
8
|
+
|
9
|
+
def run
|
10
|
+
FileUtils.mkdir(@out_dir) unless File.exists?(@out_dir)
|
11
|
+
pages = Page.find_all
|
12
|
+
puts "Generating site in: #{@out_dir}; contains #{pages.size} pages"
|
13
|
+
pages.each do |page|
|
14
|
+
puts "Generating page #{page.name} using template #{page.template.name}"
|
15
|
+
begin
|
16
|
+
page.generate(@out_dir)
|
17
|
+
rescue Templette::TempletteError => e
|
18
|
+
@errors.push(e)
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
if File.exists?(@resources_dir)
|
23
|
+
puts "Copying resources from #{@resources_dir} to #{@out_dir}"
|
24
|
+
FileUtils.cp_r("#{@resources_dir}/.", @out_dir)
|
25
|
+
end
|
26
|
+
|
27
|
+
if @errors.empty?
|
28
|
+
puts "Site generation complete!"
|
29
|
+
else
|
30
|
+
puts "SITE GENERATED WITH ERRORS!"
|
31
|
+
@errors.each { |e| puts e.message }
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
def clean
|
36
|
+
FileUtils.rm_rf(@out_dir) if File.exists?(@out_dir)
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
require 'erb'
|
2
|
+
|
3
|
+
module Templette
|
4
|
+
# Loads a template and evaluates it with ERB. When a missing method is found,
|
5
|
+
# MethodColletor loads that method into a hash, to be rendered as yaml.
|
6
|
+
class MethodCollector
|
7
|
+
include Templette::DataAccessors
|
8
|
+
|
9
|
+
def initialize(template = nil)
|
10
|
+
include_helpers(template.helpers) if template
|
11
|
+
@methods = {}
|
12
|
+
ERB.new(template.to_html, 0, "%<>").result(binding) if template
|
13
|
+
end
|
14
|
+
|
15
|
+
def method_missing(symbol)
|
16
|
+
@methods[symbol.to_s] = MethodCollector.new
|
17
|
+
end
|
18
|
+
|
19
|
+
def to_hash
|
20
|
+
return nil if @methods.empty?
|
21
|
+
hash = {}
|
22
|
+
@methods.each_pair do |k, v|
|
23
|
+
hash[k] = v.to_hash
|
24
|
+
end
|
25
|
+
hash
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
@@ -0,0 +1,88 @@
|
|
1
|
+
module Templette
|
2
|
+
|
3
|
+
# The Page is the core object of a Templette project. Pages won't get generate
|
4
|
+
# unless there are available .yml files to build out the necessary info.
|
5
|
+
#
|
6
|
+
# A general Page yaml structure example:
|
7
|
+
#
|
8
|
+
# template_name: main
|
9
|
+
# sections:
|
10
|
+
# title: Page Title
|
11
|
+
# nav:
|
12
|
+
# active-class: foo
|
13
|
+
# title: Foo!
|
14
|
+
#
|
15
|
+
# The <tt>template_name</tt> will be used to load a template.
|
16
|
+
#
|
17
|
+
# Everything in <tt>sections</tt> will be made available as methods in the template when
|
18
|
+
# it's evaluated by ERB. Yaml hash items nested within others will be loaded into nested
|
19
|
+
# objects. To call the nav title, the template should call <tt>nav.title</tt>.
|
20
|
+
|
21
|
+
class Page
|
22
|
+
|
23
|
+
include Templette::DataAccessors
|
24
|
+
attr_reader :name, :template
|
25
|
+
|
26
|
+
class <<self
|
27
|
+
def pages_dir
|
28
|
+
@@pages_dir ||= 'pages'
|
29
|
+
end
|
30
|
+
|
31
|
+
def pages_dir=(path)
|
32
|
+
@@pages_dir = path
|
33
|
+
end
|
34
|
+
|
35
|
+
# Grabs all of the yaml files found in /pages, and loads them as
|
36
|
+
# Page objects.
|
37
|
+
def find_all
|
38
|
+
Dir["#{pages_dir}/**/*.yml"].map {|f| new f }
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
def initialize(page_config)
|
43
|
+
raise PageError.new(self, "missing page #{page_config}") unless File.exists?(page_config)
|
44
|
+
|
45
|
+
data = YAML::load_file(page_config)
|
46
|
+
@name = page_config.dup
|
47
|
+
@name.slice!(self.class.pages_dir + '/')
|
48
|
+
@name.chomp!('.yml')
|
49
|
+
raise PageError.new(self, "missing required section \"template_name\" for page config #{page_config}") unless data['template_name']
|
50
|
+
@template = Template.new(data['template_name'])
|
51
|
+
|
52
|
+
raise PageError.new(self, "missing sections in yml for page config #{page_config}") unless data['sections']
|
53
|
+
generate_accessors(data['sections'])
|
54
|
+
include_helpers(template.helpers)
|
55
|
+
end
|
56
|
+
|
57
|
+
def generate(out_dir)
|
58
|
+
generate_subdirectory(out_dir)
|
59
|
+
File.open(output_file_name(out_dir), 'w') do |f|
|
60
|
+
f << ERB.new(@template.to_html, 0, "%<>").result(binding)
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
# A requriement of the Templette::DataAccessors interface. Returns self.
|
65
|
+
def page; self end
|
66
|
+
|
67
|
+
private
|
68
|
+
|
69
|
+
def output_file_name(out_dir)
|
70
|
+
"#{out_dir}/#{@name}.html"
|
71
|
+
end
|
72
|
+
|
73
|
+
def generate_subdirectory(out_dir)
|
74
|
+
FileUtils.mkdir_p(File.expand_path("#{out_dir}/" + name.chomp(File.basename(name)))) if name.index('/')
|
75
|
+
end
|
76
|
+
|
77
|
+
class Section # :nodoc:
|
78
|
+
include Templette::DataAccessors
|
79
|
+
attr_reader :page
|
80
|
+
|
81
|
+
def initialize(page, hash={})
|
82
|
+
@page = page
|
83
|
+
generate_accessors(hash)
|
84
|
+
end
|
85
|
+
|
86
|
+
end
|
87
|
+
end
|
88
|
+
end
|
@@ -0,0 +1,36 @@
|
|
1
|
+
module Templette
|
2
|
+
# The Template acts as a layout for pages. It contains an html layout for the
|
3
|
+
# page and contains method calls which are answered by helper methods or the
|
4
|
+
# loaded yaml of a page.
|
5
|
+
|
6
|
+
class Template
|
7
|
+
TEMPLATE_DIR = 'templates' unless defined?(TEMPLATE_DIR)
|
8
|
+
attr_accessor :name
|
9
|
+
|
10
|
+
# The name parameter refers to the actual filename of the template. To load
|
11
|
+
# templates/foo.html, a template_name of 'foo' should be given.
|
12
|
+
def initialize(name)
|
13
|
+
@name = name
|
14
|
+
end
|
15
|
+
|
16
|
+
def to_html
|
17
|
+
raise TemplateError.new(self, "Template rendering failed. File not found.") unless File.exists?(path)
|
18
|
+
File.read(path)
|
19
|
+
end
|
20
|
+
|
21
|
+
# Generates the yaml necessary to render empty page yaml files.
|
22
|
+
def to_yaml
|
23
|
+
{'template_name' => @name, 'sections' => MethodCollector.new(self).to_hash}.to_yaml
|
24
|
+
end
|
25
|
+
|
26
|
+
# Provides the names of helper_modules to be loaded for a template.
|
27
|
+
def helpers
|
28
|
+
["default_helper","#{name}_helper"]
|
29
|
+
end
|
30
|
+
|
31
|
+
private
|
32
|
+
def path
|
33
|
+
"#{TEMPLATE_DIR}/#{@name}.html"
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
metadata
ADDED
@@ -0,0 +1,67 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: templette
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.3.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Jacob Dunphy and Steve Holder
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
|
12
|
+
date: 2008-08-26 00:00:00 -07:00
|
13
|
+
default_executable: templette
|
14
|
+
dependencies: []
|
15
|
+
|
16
|
+
description: HTML site generation through templates
|
17
|
+
email: jacob.dunphy@gmail.com
|
18
|
+
executables:
|
19
|
+
- templette
|
20
|
+
extensions: []
|
21
|
+
|
22
|
+
extra_rdoc_files: []
|
23
|
+
|
24
|
+
files:
|
25
|
+
- lib/file_generator.rb
|
26
|
+
- lib/tasks/templette_tasks.rb
|
27
|
+
- lib/templette/data_accessors.rb
|
28
|
+
- lib/templette/errors.rb
|
29
|
+
- lib/templette/generator.rb
|
30
|
+
- lib/templette/method_collector.rb
|
31
|
+
- lib/templette/page.rb
|
32
|
+
- lib/templette/template.rb
|
33
|
+
- lib/templette.rb
|
34
|
+
- bin/templette
|
35
|
+
- bin/templette.cmd
|
36
|
+
- files/Capfile
|
37
|
+
- files/default_helper.rb
|
38
|
+
- files/deploy.rb
|
39
|
+
- files/Rakefile
|
40
|
+
has_rdoc: true
|
41
|
+
homepage: http://github.com/jdunphy/templette
|
42
|
+
post_install_message:
|
43
|
+
rdoc_options: []
|
44
|
+
|
45
|
+
require_paths:
|
46
|
+
- lib
|
47
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
48
|
+
requirements:
|
49
|
+
- - ">="
|
50
|
+
- !ruby/object:Gem::Version
|
51
|
+
version: "0"
|
52
|
+
version:
|
53
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
54
|
+
requirements:
|
55
|
+
- - ">="
|
56
|
+
- !ruby/object:Gem::Version
|
57
|
+
version: "0"
|
58
|
+
version:
|
59
|
+
requirements: []
|
60
|
+
|
61
|
+
rubyforge_project: templette
|
62
|
+
rubygems_version: 1.2.0
|
63
|
+
signing_key:
|
64
|
+
specification_version: 2
|
65
|
+
summary: HTML site generation through templates
|
66
|
+
test_files: []
|
67
|
+
|