troy 0.0.1
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/.gitignore +16 -0
- data/Gemfile +2 -0
- data/Gemfile.lock +52 -0
- data/LICENSE.txt +22 -0
- data/README.md +29 -0
- data/Rakefile +1 -0
- data/bin/troy +3 -0
- data/lib/troy.rb +30 -0
- data/lib/troy/cli.rb +41 -0
- data/lib/troy/configuration.rb +21 -0
- data/lib/troy/context.rb +19 -0
- data/lib/troy/embedded_ruby.rb +25 -0
- data/lib/troy/extension_matcher.rb +38 -0
- data/lib/troy/generator.rb +34 -0
- data/lib/troy/helpers.rb +7 -0
- data/lib/troy/markdown.rb +32 -0
- data/lib/troy/meta.rb +34 -0
- data/lib/troy/page.rb +132 -0
- data/lib/troy/server.rb +46 -0
- data/lib/troy/site.rb +98 -0
- data/lib/troy/version.rb +3 -0
- data/lib/troy/xml.rb +33 -0
- data/spec/spec_helper.rb +6 -0
- data/templates/404.erb +12 -0
- data/templates/500.erb +13 -0
- data/templates/default.erb +12 -0
- data/templates/helpers.rb +5 -0
- data/templates/index.erb +8 -0
- data/templates/script.js +2 -0
- data/templates/style.scss +2 -0
- data/templates/troy.rb +13 -0
- data/troy.gemspec +28 -0
- metadata +223 -0
data/.gitignore
ADDED
data/Gemfile
ADDED
data/Gemfile.lock
ADDED
@@ -0,0 +1,52 @@
|
|
1
|
+
PATH
|
2
|
+
remote: .
|
3
|
+
specs:
|
4
|
+
troy (0.0.1)
|
5
|
+
i18n
|
6
|
+
redcarpet
|
7
|
+
sass
|
8
|
+
sprockets
|
9
|
+
therubyracer
|
10
|
+
thor
|
11
|
+
uglifier
|
12
|
+
|
13
|
+
GEM
|
14
|
+
remote: http://rubygems.org/
|
15
|
+
specs:
|
16
|
+
diff-lcs (1.1.3)
|
17
|
+
execjs (1.4.0)
|
18
|
+
multi_json (~> 1.0)
|
19
|
+
hike (1.2.1)
|
20
|
+
i18n (0.6.1)
|
21
|
+
libv8 (3.3.10.4)
|
22
|
+
multi_json (1.3.6)
|
23
|
+
rack (1.4.1)
|
24
|
+
redcarpet (2.1.1)
|
25
|
+
rspec (2.11.0)
|
26
|
+
rspec-core (~> 2.11.0)
|
27
|
+
rspec-expectations (~> 2.11.0)
|
28
|
+
rspec-mocks (~> 2.11.0)
|
29
|
+
rspec-core (2.11.1)
|
30
|
+
rspec-expectations (2.11.3)
|
31
|
+
diff-lcs (~> 1.1.3)
|
32
|
+
rspec-mocks (2.11.3)
|
33
|
+
sass (3.2.1)
|
34
|
+
sprockets (2.6.0)
|
35
|
+
hike (~> 1.2)
|
36
|
+
multi_json (~> 1.0)
|
37
|
+
rack (~> 1.0)
|
38
|
+
tilt (~> 1.1, != 1.3.0)
|
39
|
+
therubyracer (0.10.2)
|
40
|
+
libv8 (~> 3.3.10)
|
41
|
+
thor (0.16.0)
|
42
|
+
tilt (1.3.3)
|
43
|
+
uglifier (1.3.0)
|
44
|
+
execjs (>= 0.3.0)
|
45
|
+
multi_json (~> 1.0, >= 1.0.2)
|
46
|
+
|
47
|
+
PLATFORMS
|
48
|
+
ruby
|
49
|
+
|
50
|
+
DEPENDENCIES
|
51
|
+
rspec
|
52
|
+
troy!
|
data/LICENSE.txt
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
Copyright (c) 2012 Nando Vieira
|
2
|
+
|
3
|
+
MIT License
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
6
|
+
a copy of this software and associated documentation files (the
|
7
|
+
"Software"), to deal in the Software without restriction, including
|
8
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
9
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
10
|
+
permit persons to whom the Software is furnished to do so, subject to
|
11
|
+
the following conditions:
|
12
|
+
|
13
|
+
The above copyright notice and this permission notice shall be
|
14
|
+
included in all copies or substantial portions of the Software.
|
15
|
+
|
16
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
17
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
18
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
19
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
20
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
21
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
22
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,29 @@
|
|
1
|
+
# Troy
|
2
|
+
|
3
|
+
TODO: Write a gem description
|
4
|
+
|
5
|
+
## Installation
|
6
|
+
|
7
|
+
Add this line to your application's Gemfile:
|
8
|
+
|
9
|
+
gem 'troy'
|
10
|
+
|
11
|
+
And then execute:
|
12
|
+
|
13
|
+
$ bundle
|
14
|
+
|
15
|
+
Or install it yourself as:
|
16
|
+
|
17
|
+
$ gem install troy
|
18
|
+
|
19
|
+
## Usage
|
20
|
+
|
21
|
+
TODO: Write usage instructions here
|
22
|
+
|
23
|
+
## Contributing
|
24
|
+
|
25
|
+
1. Fork it
|
26
|
+
2. Create your feature branch (`git checkout -b my-new-feature`)
|
27
|
+
3. Commit your changes (`git commit -am 'Add some feature'`)
|
28
|
+
4. Push to the branch (`git push origin my-new-feature`)
|
29
|
+
5. Create new Pull Request
|
data/Rakefile
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
require "bundler/gem_tasks"
|
data/bin/troy
ADDED
data/lib/troy.rb
ADDED
@@ -0,0 +1,30 @@
|
|
1
|
+
require "builder"
|
2
|
+
require "i18n"
|
3
|
+
require "redcarpet"
|
4
|
+
require "sass"
|
5
|
+
require "sprockets"
|
6
|
+
require "thor"
|
7
|
+
require "thor/group"
|
8
|
+
require "rack"
|
9
|
+
|
10
|
+
require "cgi"
|
11
|
+
require "fileutils"
|
12
|
+
require "forwardable"
|
13
|
+
require "ostruct"
|
14
|
+
require "pathname"
|
15
|
+
require "yaml"
|
16
|
+
|
17
|
+
require "troy/cli"
|
18
|
+
require "troy/configuration"
|
19
|
+
require "troy/context"
|
20
|
+
require "troy/embedded_ruby"
|
21
|
+
require "troy/extension_matcher"
|
22
|
+
require "troy/generator"
|
23
|
+
require "troy/helpers"
|
24
|
+
require "troy/markdown"
|
25
|
+
require "troy/meta"
|
26
|
+
require "troy/page"
|
27
|
+
require "troy/xml"
|
28
|
+
require "troy/server"
|
29
|
+
require "troy/site"
|
30
|
+
require "troy/version"
|
data/lib/troy/cli.rb
ADDED
@@ -0,0 +1,41 @@
|
|
1
|
+
module Troy
|
2
|
+
class Cli < Thor
|
3
|
+
check_unknown_options!
|
4
|
+
|
5
|
+
def self.exit_on_failure?
|
6
|
+
true
|
7
|
+
end
|
8
|
+
|
9
|
+
def initialize(args = [], options = {}, config = {})
|
10
|
+
if config[:current_task].name == "new" && args.empty?
|
11
|
+
raise Error, "The site path is required. For details run: troy help new"
|
12
|
+
end
|
13
|
+
|
14
|
+
super
|
15
|
+
end
|
16
|
+
|
17
|
+
desc "new SITE", "Generate a new site structure"
|
18
|
+
def new(path)
|
19
|
+
generator = Generator.new
|
20
|
+
generator.destination_root = path
|
21
|
+
generator.invoke_all
|
22
|
+
end
|
23
|
+
|
24
|
+
desc "export", "Generate static files"
|
25
|
+
def export
|
26
|
+
Troy::Site.new(Dir.pwd).export
|
27
|
+
end
|
28
|
+
|
29
|
+
desc "watch", "Watch and auto export site"
|
30
|
+
def watch
|
31
|
+
Troy::Site.new(Dir.pwd).export
|
32
|
+
end
|
33
|
+
|
34
|
+
desc "server", "Start a server"
|
35
|
+
option :port, :type => :numeric, :default => 9292, :aliases => "-p"
|
36
|
+
def server
|
37
|
+
handler = Rack::Handler::Thin rescue Rack::Handler::WEBrick
|
38
|
+
handler.run Troy::Server.new(File.join(Dir.pwd, "public")), :Port => options[:port]
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
module Troy
|
2
|
+
def self.configuration
|
3
|
+
@configuration ||= Configuration.new
|
4
|
+
end
|
5
|
+
|
6
|
+
def self.configure(&block)
|
7
|
+
yield configuration
|
8
|
+
end
|
9
|
+
|
10
|
+
class Configuration < OpenStruct
|
11
|
+
def assets
|
12
|
+
@assets ||= Configuration.new
|
13
|
+
end
|
14
|
+
|
15
|
+
def i18n
|
16
|
+
@i18n ||= Configuration.new.tap do |config|
|
17
|
+
config.load_path = ["config/locales/*.yml"]
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
data/lib/troy/context.rb
ADDED
@@ -0,0 +1,19 @@
|
|
1
|
+
module Troy
|
2
|
+
class Context
|
3
|
+
def initialize(options = {})
|
4
|
+
options.each do |name, value|
|
5
|
+
instance_variable_set("@#{name}", value)
|
6
|
+
|
7
|
+
instance_eval <<-RUBY
|
8
|
+
def #{name} # def name
|
9
|
+
@#{name} # @name
|
10
|
+
end # end
|
11
|
+
RUBY
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
def to_binding
|
16
|
+
binding
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
module Troy
|
2
|
+
class EmbeddedRuby
|
3
|
+
# The template content.
|
4
|
+
#
|
5
|
+
attr_reader :content
|
6
|
+
|
7
|
+
# The data that must be rendered within
|
8
|
+
# the Troy::Context object.
|
9
|
+
#
|
10
|
+
attr_reader :data
|
11
|
+
|
12
|
+
def initialize(content, data)
|
13
|
+
@content = content
|
14
|
+
@data = data
|
15
|
+
end
|
16
|
+
|
17
|
+
def context
|
18
|
+
@context ||= Context.new(data).extend(Helpers)
|
19
|
+
end
|
20
|
+
|
21
|
+
def render
|
22
|
+
ERB.new(content).result context.to_binding
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
@@ -0,0 +1,38 @@
|
|
1
|
+
module Troy
|
2
|
+
class ExtensionMatcher
|
3
|
+
#
|
4
|
+
#
|
5
|
+
attr_reader :path
|
6
|
+
|
7
|
+
#
|
8
|
+
#
|
9
|
+
attr_reader :performed
|
10
|
+
|
11
|
+
#
|
12
|
+
#
|
13
|
+
attr_reader :matchers
|
14
|
+
|
15
|
+
def initialize(path)
|
16
|
+
@path = path
|
17
|
+
@matchers = {}
|
18
|
+
end
|
19
|
+
|
20
|
+
def on(extension, &block)
|
21
|
+
matchers[".#{extension}"] = block
|
22
|
+
self
|
23
|
+
end
|
24
|
+
|
25
|
+
def default(&block)
|
26
|
+
matchers["default"] = block
|
27
|
+
self
|
28
|
+
end
|
29
|
+
|
30
|
+
def match
|
31
|
+
matchers.each do |ext, handler|
|
32
|
+
return handler.call if File.extname(path) == ext
|
33
|
+
end
|
34
|
+
|
35
|
+
matchers["default"].call if matchers["default"]
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
@@ -0,0 +1,34 @@
|
|
1
|
+
module Troy
|
2
|
+
# The Troy::Generator class will create a new book structure.
|
3
|
+
#
|
4
|
+
# ebook = Troy::Generator.new
|
5
|
+
# ebook.destination_root = "/some/path/book-name"
|
6
|
+
# ebook.invoke_all
|
7
|
+
#
|
8
|
+
class Generator < Thor::Group
|
9
|
+
include Thor::Actions
|
10
|
+
|
11
|
+
desc "Generate a new site structure"
|
12
|
+
|
13
|
+
def self.source_root
|
14
|
+
File.expand_path("../../../templates", __FILE__)
|
15
|
+
end
|
16
|
+
|
17
|
+
def create_directories
|
18
|
+
empty_directory "assets/javascripts"
|
19
|
+
empty_directory "assets/stylesheets"
|
20
|
+
empty_directory "assets/images"
|
21
|
+
empty_directory "source"
|
22
|
+
empty_directory "config"
|
23
|
+
empty_directory "layouts"
|
24
|
+
end
|
25
|
+
|
26
|
+
def copy_files
|
27
|
+
copy_file "helpers.rb", "config/helpers.rb"
|
28
|
+
copy_file "default.erb", "layouts/default.erb"
|
29
|
+
copy_file "index.erb", "source/index.erb"
|
30
|
+
copy_file "404.erb", "source/404.erb"
|
31
|
+
copy_file "500.erb", "source/500.erb"
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
data/lib/troy/helpers.rb
ADDED
@@ -0,0 +1,32 @@
|
|
1
|
+
module Troy
|
2
|
+
class Markdown
|
3
|
+
# Create a new Redcarpet renderer, that prepares the code block
|
4
|
+
# to use Prisme.js syntax.
|
5
|
+
#
|
6
|
+
class Renderer < Redcarpet::Render::HTML
|
7
|
+
def block_code(code, language)
|
8
|
+
%[<pre class="language-#{language}"><code>#{CGI.escapeHTML(code)}</code></pre>]
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
# Set the Markdown markup that must be rendered.
|
13
|
+
#
|
14
|
+
attr_reader :markup
|
15
|
+
|
16
|
+
def initialize(markup)
|
17
|
+
@markup = markup
|
18
|
+
end
|
19
|
+
|
20
|
+
def renderer
|
21
|
+
@renderer ||= Redcarpet::Markdown.new(Renderer, {
|
22
|
+
:autolink => true,
|
23
|
+
:space_after_headers => true,
|
24
|
+
:fenced_code_blocks => true
|
25
|
+
})
|
26
|
+
end
|
27
|
+
|
28
|
+
def to_html
|
29
|
+
renderer.render(markup)
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
data/lib/troy/meta.rb
ADDED
@@ -0,0 +1,34 @@
|
|
1
|
+
module Troy
|
2
|
+
class Meta
|
3
|
+
extend Forwardable
|
4
|
+
def_delegators :data, :[], :fetch, :key?
|
5
|
+
|
6
|
+
REGEX = /^---\n(.*?)\n---\n+/m
|
7
|
+
|
8
|
+
attr_reader :file
|
9
|
+
|
10
|
+
def initialize(file)
|
11
|
+
@file = file
|
12
|
+
end
|
13
|
+
|
14
|
+
def content
|
15
|
+
@content ||= raw.gsub(REGEX, "")
|
16
|
+
end
|
17
|
+
|
18
|
+
def data
|
19
|
+
@data ||= (raw =~ REGEX ? YAML.load(raw[REGEX, 1]) : {})
|
20
|
+
end
|
21
|
+
|
22
|
+
def method_missing(name, *args, &block)
|
23
|
+
self[name]
|
24
|
+
end
|
25
|
+
|
26
|
+
def respond_to_missing?(method, include_private = false)
|
27
|
+
true
|
28
|
+
end
|
29
|
+
|
30
|
+
def raw
|
31
|
+
@raw ||= File.read(file)
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
data/lib/troy/page.rb
ADDED
@@ -0,0 +1,132 @@
|
|
1
|
+
module Troy
|
2
|
+
class Page
|
3
|
+
extend Forwardable
|
4
|
+
|
5
|
+
def_delegators :meta, :template
|
6
|
+
|
7
|
+
# Set the page path, which must contain a valid
|
8
|
+
# meta section and page content.
|
9
|
+
#
|
10
|
+
attr_reader :path
|
11
|
+
|
12
|
+
# Set the meta data for this particular page.
|
13
|
+
#
|
14
|
+
attr_reader :meta
|
15
|
+
|
16
|
+
# Set the current site object, which contains reference to
|
17
|
+
# all existing pages.
|
18
|
+
#
|
19
|
+
attr_reader :site
|
20
|
+
|
21
|
+
# Initialize a new page, which can be simply rendered or
|
22
|
+
# persisted to the filesystem.
|
23
|
+
#
|
24
|
+
def initialize(site, path)
|
25
|
+
@site = site
|
26
|
+
@path = path
|
27
|
+
@meta = Meta.new(path)
|
28
|
+
end
|
29
|
+
|
30
|
+
#
|
31
|
+
#
|
32
|
+
def method_missing(name, *args, &block)
|
33
|
+
return meta[name.to_s] if meta.key?(name.to_s)
|
34
|
+
super
|
35
|
+
end
|
36
|
+
|
37
|
+
#
|
38
|
+
#
|
39
|
+
def respond_to_missing?(name, include_private = false)
|
40
|
+
meta.key?(name.to_s)
|
41
|
+
end
|
42
|
+
|
43
|
+
#
|
44
|
+
#
|
45
|
+
def content
|
46
|
+
ExtensionMatcher.new(path)
|
47
|
+
.default { meta.content }
|
48
|
+
.on("builder") { XML.new(meta.content, to_context).to_xml }
|
49
|
+
.on("erb") { EmbeddedRuby.new(meta.content, to_context).render }
|
50
|
+
.on("md") { Markdown.new(meta.content).to_html }
|
51
|
+
.match
|
52
|
+
end
|
53
|
+
|
54
|
+
#
|
55
|
+
#
|
56
|
+
def to_context
|
57
|
+
{
|
58
|
+
:page => self,
|
59
|
+
:site => site
|
60
|
+
}
|
61
|
+
end
|
62
|
+
|
63
|
+
# Render the current page.
|
64
|
+
#
|
65
|
+
def render
|
66
|
+
ExtensionMatcher.new(path)
|
67
|
+
.default { content }
|
68
|
+
.on("html") { render_erb }
|
69
|
+
.on("md") { render_erb }
|
70
|
+
.on("erb") { render_erb }
|
71
|
+
.match
|
72
|
+
end
|
73
|
+
|
74
|
+
#
|
75
|
+
#
|
76
|
+
def permalink
|
77
|
+
meta.fetch("permalink", File.basename(path).gsub(/\..*?$/, ""))
|
78
|
+
end
|
79
|
+
|
80
|
+
#
|
81
|
+
#
|
82
|
+
def filename
|
83
|
+
ExtensionMatcher.new(path)
|
84
|
+
.default { "#{permalink}.html" }
|
85
|
+
.on("builder") { "#{permalink}.xml" }
|
86
|
+
.on("xml") { "#{permalink}.xml" }
|
87
|
+
.match
|
88
|
+
end
|
89
|
+
|
90
|
+
#
|
91
|
+
#
|
92
|
+
def layout
|
93
|
+
site.root.join("layouts/#{meta.fetch("layout", "default")}.erb")
|
94
|
+
end
|
95
|
+
|
96
|
+
#
|
97
|
+
#
|
98
|
+
def render_erb
|
99
|
+
if layout.exist?
|
100
|
+
EmbeddedRuby.new(
|
101
|
+
layout.read,
|
102
|
+
to_context.merge(:content => content)
|
103
|
+
).render
|
104
|
+
else
|
105
|
+
content
|
106
|
+
end
|
107
|
+
end
|
108
|
+
|
109
|
+
# Save current page to the specified path.
|
110
|
+
#
|
111
|
+
def save_to(path)
|
112
|
+
File.open(path, "w") {|file| file << render }
|
113
|
+
end
|
114
|
+
|
115
|
+
#
|
116
|
+
#
|
117
|
+
def output_file
|
118
|
+
base = File.dirname(path)
|
119
|
+
.gsub(site.root.join("source").to_s, "")
|
120
|
+
.gsub(%r[^/], "")
|
121
|
+
|
122
|
+
site.root.join("public", base, filename)
|
123
|
+
end
|
124
|
+
|
125
|
+
#
|
126
|
+
#
|
127
|
+
def save
|
128
|
+
FileUtils.mkdir_p(File.dirname(output_file))
|
129
|
+
save_to(output_file)
|
130
|
+
end
|
131
|
+
end
|
132
|
+
end
|
data/lib/troy/server.rb
ADDED
@@ -0,0 +1,46 @@
|
|
1
|
+
module Troy
|
2
|
+
class Server
|
3
|
+
attr_reader :root, :request
|
4
|
+
|
5
|
+
def initialize(root)
|
6
|
+
@root = Pathname.new(root)
|
7
|
+
end
|
8
|
+
|
9
|
+
def call(env)
|
10
|
+
@request = Rack::Request.new(env)
|
11
|
+
process
|
12
|
+
end
|
13
|
+
|
14
|
+
def render(status, content_type, path)
|
15
|
+
last_modified = path.mtime.httpdate
|
16
|
+
return [304, {}, []] if request.env["HTTP_IF_MODIFIED_SINCE"] == last_modified
|
17
|
+
|
18
|
+
headers = {
|
19
|
+
"Content-Type" => content_type,
|
20
|
+
"Last-Modified" => last_modified
|
21
|
+
}
|
22
|
+
|
23
|
+
content = request.head? ? [] : [path.read]
|
24
|
+
|
25
|
+
[status, headers, content]
|
26
|
+
end
|
27
|
+
|
28
|
+
def process
|
29
|
+
path = request.path
|
30
|
+
path = "index" if path == "/"
|
31
|
+
path = root.join(path.gsub(%r[^/], ""))
|
32
|
+
|
33
|
+
if (_path = Pathname.new("#{path}.html")).file?
|
34
|
+
render(200, "text/html", _path)
|
35
|
+
elsif (_path = Pathname.new("#{path}.xml")).file?
|
36
|
+
render(200, "text/xml", _path)
|
37
|
+
elsif path.file? && path.extname !~ /\.(html?|xml)$/
|
38
|
+
render(200, Rack::Mime.mime_type(path.extname, "text/plain"), path)
|
39
|
+
else
|
40
|
+
render(404, "text/html", root.join("404.html"))
|
41
|
+
end
|
42
|
+
rescue Exception => error
|
43
|
+
render(500, "text/html", root.join("500.html"))
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
data/lib/troy/site.rb
ADDED
@@ -0,0 +1,98 @@
|
|
1
|
+
module Troy
|
2
|
+
class Site
|
3
|
+
attr_accessor :root
|
4
|
+
|
5
|
+
def initialize(root)
|
6
|
+
@root = Pathname.new(root).realpath
|
7
|
+
|
8
|
+
load_configuration
|
9
|
+
load_extensions
|
10
|
+
set_locale
|
11
|
+
end
|
12
|
+
|
13
|
+
#
|
14
|
+
#
|
15
|
+
def load_extensions
|
16
|
+
Dir[root.join("config/**/*helpers.rb")].each do |file|
|
17
|
+
require file
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
#
|
22
|
+
#
|
23
|
+
def set_locale
|
24
|
+
I18n.load_path += Troy.configuration.i18n.load_path
|
25
|
+
I18n.locale = Troy.configuration.i18n.locale
|
26
|
+
end
|
27
|
+
|
28
|
+
#
|
29
|
+
#
|
30
|
+
def load_configuration
|
31
|
+
load root.join("config/troy.rb")
|
32
|
+
end
|
33
|
+
|
34
|
+
#
|
35
|
+
#
|
36
|
+
def export
|
37
|
+
remove_public_dir
|
38
|
+
export_assets
|
39
|
+
export_pages
|
40
|
+
copy_images
|
41
|
+
end
|
42
|
+
|
43
|
+
#
|
44
|
+
#
|
45
|
+
def copy_images
|
46
|
+
FileUtils.cp_r(root.join("assets/images"), root.join("public/images"))
|
47
|
+
end
|
48
|
+
|
49
|
+
#
|
50
|
+
#
|
51
|
+
def remove_public_dir
|
52
|
+
FileUtils.rm_rf(root.join("public"))
|
53
|
+
end
|
54
|
+
|
55
|
+
#
|
56
|
+
#
|
57
|
+
def export_pages
|
58
|
+
pages.each(&:save)
|
59
|
+
end
|
60
|
+
|
61
|
+
#
|
62
|
+
#
|
63
|
+
def copy_assets
|
64
|
+
FileUtils.cp_r(root.join("assets"), root.join("public"))
|
65
|
+
end
|
66
|
+
|
67
|
+
#
|
68
|
+
#
|
69
|
+
def export_assets
|
70
|
+
sprockets = Sprockets::Environment.new
|
71
|
+
sprockets.append_path root.join("assets/javascripts")
|
72
|
+
sprockets.append_path root.join("assets/stylesheets")
|
73
|
+
|
74
|
+
Troy.configuration.assets.precompile.each do |asset_name|
|
75
|
+
asset = sprockets[asset_name]
|
76
|
+
output_file = asset.pathname.to_s
|
77
|
+
.gsub(root.join("assets").to_s, "")
|
78
|
+
.gsub(%r[^/], "")
|
79
|
+
.gsub(/\.scss$/, ".css")
|
80
|
+
.gsub(/\.coffee$/, ".js")
|
81
|
+
|
82
|
+
asset.write_to root.join("public/#{output_file}")
|
83
|
+
end
|
84
|
+
end
|
85
|
+
|
86
|
+
#
|
87
|
+
#
|
88
|
+
def source
|
89
|
+
Dir[root.join("source/**/*.{html,erb,md,builder,xml}").to_s]
|
90
|
+
end
|
91
|
+
|
92
|
+
# Return all pages wrapped in Troy::Page class.
|
93
|
+
#
|
94
|
+
def pages
|
95
|
+
@pages ||= source.map {|path| Page.new(self, path) }
|
96
|
+
end
|
97
|
+
end
|
98
|
+
end
|
data/lib/troy/version.rb
ADDED
data/lib/troy/xml.rb
ADDED
@@ -0,0 +1,33 @@
|
|
1
|
+
module Troy
|
2
|
+
class XML
|
3
|
+
# The XML content.
|
4
|
+
#
|
5
|
+
attr_reader :content
|
6
|
+
|
7
|
+
# The data that must be rendered within
|
8
|
+
# the Troy::Context object.
|
9
|
+
#
|
10
|
+
attr_reader :data
|
11
|
+
|
12
|
+
def initialize(content, data)
|
13
|
+
@content = content
|
14
|
+
@data = data
|
15
|
+
end
|
16
|
+
|
17
|
+
def context
|
18
|
+
@context ||= Context.new(data.merge(:xml => xml)).extend(Helpers)
|
19
|
+
end
|
20
|
+
|
21
|
+
def xml
|
22
|
+
@xml ||= Builder::XmlMarkup.new(:indent => 2)
|
23
|
+
end
|
24
|
+
|
25
|
+
def to_xml
|
26
|
+
@to_xml ||= begin
|
27
|
+
xml.instruct!
|
28
|
+
context.instance_eval(content)
|
29
|
+
xml.target!
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
data/spec/spec_helper.rb
ADDED
data/templates/404.erb
ADDED
data/templates/500.erb
ADDED
@@ -0,0 +1,13 @@
|
|
1
|
+
---
|
2
|
+
title: Sad Panda is Sad!
|
3
|
+
---
|
4
|
+
|
5
|
+
<h1>Sad Panda is Sad!</h1>
|
6
|
+
<p>
|
7
|
+
Sorry! We couldn’t process your request for now.
|
8
|
+
</p>
|
9
|
+
|
10
|
+
<p>
|
11
|
+
Try going back to the <a href="/">home page</a> or
|
12
|
+
<a href="javascript:location.reload();">reloading this page</a>.
|
13
|
+
</p>
|
data/templates/index.erb
ADDED
data/templates/script.js
ADDED
data/templates/troy.rb
ADDED
@@ -0,0 +1,13 @@
|
|
1
|
+
Troy.configure do |config|
|
2
|
+
# Set the current locale.
|
3
|
+
config.i18n.locale = "en"
|
4
|
+
|
5
|
+
# Make sure you download the correct file from
|
6
|
+
# https://github.com/svenfuchs/rails-i18n/tree/master/rails/locale
|
7
|
+
# and place it at `config/locales/*.yml`.
|
8
|
+
config.1i8n.load_path = Dir["config/locales/*.yml"]
|
9
|
+
|
10
|
+
# These are the assets that you want
|
11
|
+
# to precompile.
|
12
|
+
config.assets.precompile = %w[style.css script.js]
|
13
|
+
end
|
data/troy.gemspec
ADDED
@@ -0,0 +1,28 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
require "./lib/troy/version"
|
3
|
+
|
4
|
+
Gem::Specification.new do |gem|
|
5
|
+
gem.name = "troy"
|
6
|
+
gem.version = Troy::VERSION
|
7
|
+
gem.authors = ["Nando Vieira"]
|
8
|
+
gem.email = ["fnando.vieira@gmail.com"]
|
9
|
+
gem.description = "A static site generator"
|
10
|
+
gem.summary = gem.description
|
11
|
+
gem.homepage = "http://github.com/fnando/troy"
|
12
|
+
|
13
|
+
gem.files = `git ls-files`.split($/)
|
14
|
+
gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
|
15
|
+
gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
|
16
|
+
gem.require_paths = ["lib"]
|
17
|
+
|
18
|
+
gem.add_dependency "i18n"
|
19
|
+
gem.add_dependency "thor"
|
20
|
+
gem.add_dependency "redcarpet"
|
21
|
+
gem.add_dependency "sass"
|
22
|
+
gem.add_dependency "sprockets"
|
23
|
+
gem.add_dependency "uglifier"
|
24
|
+
gem.add_dependency "therubyracer"
|
25
|
+
gem.add_dependency "rack"
|
26
|
+
|
27
|
+
gem.add_development_dependency "rspec"
|
28
|
+
end
|
metadata
ADDED
@@ -0,0 +1,223 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: troy
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1
|
5
|
+
prerelease:
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- Nando Vieira
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
date: 2012-10-09 00:00:00.000000000 Z
|
13
|
+
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
15
|
+
name: i18n
|
16
|
+
requirement: !ruby/object:Gem::Requirement
|
17
|
+
none: false
|
18
|
+
requirements:
|
19
|
+
- - ! '>='
|
20
|
+
- !ruby/object:Gem::Version
|
21
|
+
version: '0'
|
22
|
+
type: :runtime
|
23
|
+
prerelease: false
|
24
|
+
version_requirements: !ruby/object:Gem::Requirement
|
25
|
+
none: false
|
26
|
+
requirements:
|
27
|
+
- - ! '>='
|
28
|
+
- !ruby/object:Gem::Version
|
29
|
+
version: '0'
|
30
|
+
- !ruby/object:Gem::Dependency
|
31
|
+
name: thor
|
32
|
+
requirement: !ruby/object:Gem::Requirement
|
33
|
+
none: false
|
34
|
+
requirements:
|
35
|
+
- - ! '>='
|
36
|
+
- !ruby/object:Gem::Version
|
37
|
+
version: '0'
|
38
|
+
type: :runtime
|
39
|
+
prerelease: false
|
40
|
+
version_requirements: !ruby/object:Gem::Requirement
|
41
|
+
none: false
|
42
|
+
requirements:
|
43
|
+
- - ! '>='
|
44
|
+
- !ruby/object:Gem::Version
|
45
|
+
version: '0'
|
46
|
+
- !ruby/object:Gem::Dependency
|
47
|
+
name: redcarpet
|
48
|
+
requirement: !ruby/object:Gem::Requirement
|
49
|
+
none: false
|
50
|
+
requirements:
|
51
|
+
- - ! '>='
|
52
|
+
- !ruby/object:Gem::Version
|
53
|
+
version: '0'
|
54
|
+
type: :runtime
|
55
|
+
prerelease: false
|
56
|
+
version_requirements: !ruby/object:Gem::Requirement
|
57
|
+
none: false
|
58
|
+
requirements:
|
59
|
+
- - ! '>='
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '0'
|
62
|
+
- !ruby/object:Gem::Dependency
|
63
|
+
name: sass
|
64
|
+
requirement: !ruby/object:Gem::Requirement
|
65
|
+
none: false
|
66
|
+
requirements:
|
67
|
+
- - ! '>='
|
68
|
+
- !ruby/object:Gem::Version
|
69
|
+
version: '0'
|
70
|
+
type: :runtime
|
71
|
+
prerelease: false
|
72
|
+
version_requirements: !ruby/object:Gem::Requirement
|
73
|
+
none: false
|
74
|
+
requirements:
|
75
|
+
- - ! '>='
|
76
|
+
- !ruby/object:Gem::Version
|
77
|
+
version: '0'
|
78
|
+
- !ruby/object:Gem::Dependency
|
79
|
+
name: sprockets
|
80
|
+
requirement: !ruby/object:Gem::Requirement
|
81
|
+
none: false
|
82
|
+
requirements:
|
83
|
+
- - ! '>='
|
84
|
+
- !ruby/object:Gem::Version
|
85
|
+
version: '0'
|
86
|
+
type: :runtime
|
87
|
+
prerelease: false
|
88
|
+
version_requirements: !ruby/object:Gem::Requirement
|
89
|
+
none: false
|
90
|
+
requirements:
|
91
|
+
- - ! '>='
|
92
|
+
- !ruby/object:Gem::Version
|
93
|
+
version: '0'
|
94
|
+
- !ruby/object:Gem::Dependency
|
95
|
+
name: uglifier
|
96
|
+
requirement: !ruby/object:Gem::Requirement
|
97
|
+
none: false
|
98
|
+
requirements:
|
99
|
+
- - ! '>='
|
100
|
+
- !ruby/object:Gem::Version
|
101
|
+
version: '0'
|
102
|
+
type: :runtime
|
103
|
+
prerelease: false
|
104
|
+
version_requirements: !ruby/object:Gem::Requirement
|
105
|
+
none: false
|
106
|
+
requirements:
|
107
|
+
- - ! '>='
|
108
|
+
- !ruby/object:Gem::Version
|
109
|
+
version: '0'
|
110
|
+
- !ruby/object:Gem::Dependency
|
111
|
+
name: therubyracer
|
112
|
+
requirement: !ruby/object:Gem::Requirement
|
113
|
+
none: false
|
114
|
+
requirements:
|
115
|
+
- - ! '>='
|
116
|
+
- !ruby/object:Gem::Version
|
117
|
+
version: '0'
|
118
|
+
type: :runtime
|
119
|
+
prerelease: false
|
120
|
+
version_requirements: !ruby/object:Gem::Requirement
|
121
|
+
none: false
|
122
|
+
requirements:
|
123
|
+
- - ! '>='
|
124
|
+
- !ruby/object:Gem::Version
|
125
|
+
version: '0'
|
126
|
+
- !ruby/object:Gem::Dependency
|
127
|
+
name: rack
|
128
|
+
requirement: !ruby/object:Gem::Requirement
|
129
|
+
none: false
|
130
|
+
requirements:
|
131
|
+
- - ! '>='
|
132
|
+
- !ruby/object:Gem::Version
|
133
|
+
version: '0'
|
134
|
+
type: :runtime
|
135
|
+
prerelease: false
|
136
|
+
version_requirements: !ruby/object:Gem::Requirement
|
137
|
+
none: false
|
138
|
+
requirements:
|
139
|
+
- - ! '>='
|
140
|
+
- !ruby/object:Gem::Version
|
141
|
+
version: '0'
|
142
|
+
- !ruby/object:Gem::Dependency
|
143
|
+
name: rspec
|
144
|
+
requirement: !ruby/object:Gem::Requirement
|
145
|
+
none: false
|
146
|
+
requirements:
|
147
|
+
- - ! '>='
|
148
|
+
- !ruby/object:Gem::Version
|
149
|
+
version: '0'
|
150
|
+
type: :development
|
151
|
+
prerelease: false
|
152
|
+
version_requirements: !ruby/object:Gem::Requirement
|
153
|
+
none: false
|
154
|
+
requirements:
|
155
|
+
- - ! '>='
|
156
|
+
- !ruby/object:Gem::Version
|
157
|
+
version: '0'
|
158
|
+
description: A static site generator
|
159
|
+
email:
|
160
|
+
- fnando.vieira@gmail.com
|
161
|
+
executables:
|
162
|
+
- troy
|
163
|
+
extensions: []
|
164
|
+
extra_rdoc_files: []
|
165
|
+
files:
|
166
|
+
- .gitignore
|
167
|
+
- Gemfile
|
168
|
+
- Gemfile.lock
|
169
|
+
- LICENSE.txt
|
170
|
+
- README.md
|
171
|
+
- Rakefile
|
172
|
+
- bin/troy
|
173
|
+
- lib/troy.rb
|
174
|
+
- lib/troy/cli.rb
|
175
|
+
- lib/troy/configuration.rb
|
176
|
+
- lib/troy/context.rb
|
177
|
+
- lib/troy/embedded_ruby.rb
|
178
|
+
- lib/troy/extension_matcher.rb
|
179
|
+
- lib/troy/generator.rb
|
180
|
+
- lib/troy/helpers.rb
|
181
|
+
- lib/troy/markdown.rb
|
182
|
+
- lib/troy/meta.rb
|
183
|
+
- lib/troy/page.rb
|
184
|
+
- lib/troy/server.rb
|
185
|
+
- lib/troy/site.rb
|
186
|
+
- lib/troy/version.rb
|
187
|
+
- lib/troy/xml.rb
|
188
|
+
- spec/spec_helper.rb
|
189
|
+
- templates/404.erb
|
190
|
+
- templates/500.erb
|
191
|
+
- templates/default.erb
|
192
|
+
- templates/helpers.rb
|
193
|
+
- templates/index.erb
|
194
|
+
- templates/script.js
|
195
|
+
- templates/style.scss
|
196
|
+
- templates/troy.rb
|
197
|
+
- troy.gemspec
|
198
|
+
homepage: http://github.com/fnando/troy
|
199
|
+
licenses: []
|
200
|
+
post_install_message:
|
201
|
+
rdoc_options: []
|
202
|
+
require_paths:
|
203
|
+
- lib
|
204
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
205
|
+
none: false
|
206
|
+
requirements:
|
207
|
+
- - ! '>='
|
208
|
+
- !ruby/object:Gem::Version
|
209
|
+
version: '0'
|
210
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
211
|
+
none: false
|
212
|
+
requirements:
|
213
|
+
- - ! '>='
|
214
|
+
- !ruby/object:Gem::Version
|
215
|
+
version: '0'
|
216
|
+
requirements: []
|
217
|
+
rubyforge_project:
|
218
|
+
rubygems_version: 1.8.23
|
219
|
+
signing_key:
|
220
|
+
specification_version: 3
|
221
|
+
summary: A static site generator
|
222
|
+
test_files:
|
223
|
+
- spec/spec_helper.rb
|