Initial import
This commit is contained in:
commit
4cc4e303ab
3
.gitignore
vendored
Normal file
3
.gitignore
vendored
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
/*.gem
|
||||||
|
.DS_Store
|
||||||
|
.rvmrc
|
20
LICENSE
Normal file
20
LICENSE
Normal file
|
@ -0,0 +1,20 @@
|
||||||
|
Copyright (c) 2010 Jakub Šťastný aka Botanicus
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining
|
||||||
|
a copy of this software and associated documentation files (the
|
||||||
|
"Software"), to deal in the Software without restriction, including
|
||||||
|
without limitation the rights to use, copy, modify, merge, publish,
|
||||||
|
distribute, sublicense, and/or sell copies of the Software, and to
|
||||||
|
permit persons to whom the Software is furnished to do so, subject to
|
||||||
|
the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be
|
||||||
|
included in all copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||||
|
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||||
|
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||||
|
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||||
|
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||||
|
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||||
|
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
18
README.textile
Normal file
18
README.textile
Normal file
|
@ -0,0 +1,18 @@
|
||||||
|
h1. Why you should be interested in ace?
|
||||||
|
|
||||||
|
In Ace, every page is an instance
|
||||||
|
Typically I want to define methods, like @post.excerpt
|
||||||
|
|
||||||
|
There are also *generators* available for easier generating items on the fly.
|
||||||
|
|
||||||
|
Ace has *template inheritance*. I love template inheritance, it's more flexible pattern than layouts.
|
||||||
|
|
||||||
|
Tasks for deployment included.
|
||||||
|
|
||||||
|
h1. The boot process
|
||||||
|
|
||||||
|
# load @boot.rb@ where the
|
||||||
|
# load the rules (controllers / globs mapping)
|
||||||
|
# load & instantiate the items: only the renderables (concrete post)
|
||||||
|
# run the filters, layoutin' ... actually this can be defined in the controller
|
||||||
|
# match the routes, write the files
|
53
ace.gemspec
Executable file
53
ace.gemspec
Executable file
|
@ -0,0 +1,53 @@
|
||||||
|
#!/usr/bin/env gem build
|
||||||
|
# encoding: utf-8
|
||||||
|
|
||||||
|
require "base64"
|
||||||
|
require File.expand_path("../lib/ace/version", __FILE__)
|
||||||
|
|
||||||
|
Gem::Specification.new do |s|
|
||||||
|
s.name = "ace"
|
||||||
|
s.version = Ace::VERSION
|
||||||
|
s.authors = ["Jakub Šťastný aka Botanicus"]
|
||||||
|
s.homepage = "http://github.com/botanicus/ace"
|
||||||
|
s.summary = "Ace is highly flexible static pages generator with template inheritance."
|
||||||
|
s.description = "" # TODO: long description
|
||||||
|
s.cert_chain = nil
|
||||||
|
s.email = Base64.decode64("c3Rhc3RueUAxMDFpZGVhcy5jeg==\n")
|
||||||
|
s.has_rdoc = true
|
||||||
|
|
||||||
|
# files
|
||||||
|
s.files = `git ls-files`.split("\n")
|
||||||
|
|
||||||
|
s.executables = Dir["bin/*"].map(&File.method(:basename))
|
||||||
|
s.default_executable = "ace"
|
||||||
|
s.require_paths = ["lib"]
|
||||||
|
|
||||||
|
# Ruby version
|
||||||
|
# Current JRuby with --1.9 switch has RUBY_VERSION set to "1.9.2dev"
|
||||||
|
# and RubyGems don't play well with it, so we have to set minimal
|
||||||
|
# Ruby version to 1.9, even if it actually is 1.9.1
|
||||||
|
s.required_ruby_version = ::Gem::Requirement.new("~> 1.9")
|
||||||
|
|
||||||
|
# Dependencies
|
||||||
|
# RubyGems has runtime dependencies (add_dependency) and
|
||||||
|
# development dependencies (add_development_dependency)
|
||||||
|
# Ace isn't a monolithic framework, so you might want
|
||||||
|
# to use just one specific part of it, so it has no sense
|
||||||
|
# to specify dependencies for the whole gem. If you want
|
||||||
|
# to install everything what you need for start with Ace,
|
||||||
|
# just run gem install ace --development
|
||||||
|
|
||||||
|
s.add_dependency "template-inheritance"
|
||||||
|
s.add_development_dependency "simple-templater", ">= 0.0.1.2"
|
||||||
|
|
||||||
|
begin
|
||||||
|
require "changelog"
|
||||||
|
rescue LoadError
|
||||||
|
warn "You have to have changelog gem installed for post install message"
|
||||||
|
else
|
||||||
|
s.post_install_message = CHANGELOG.new.version_changes
|
||||||
|
end
|
||||||
|
|
||||||
|
# RubyForge
|
||||||
|
s.rubyforge_project = "ace"
|
||||||
|
end
|
6
ace.pre.gemspec
Executable file
6
ace.pre.gemspec
Executable file
|
@ -0,0 +1,6 @@
|
||||||
|
#!/usr/bin/env gem build
|
||||||
|
# encoding: utf-8
|
||||||
|
|
||||||
|
eval(File.read("ace.gemspec")).tap do |specification|
|
||||||
|
specification.version = "#{specification.version}.pre"
|
||||||
|
end
|
76
bin/ace
Executable file
76
bin/ace
Executable file
|
@ -0,0 +1,76 @@
|
||||||
|
#!/usr/bin/env ruby
|
||||||
|
# encoding: utf-8
|
||||||
|
|
||||||
|
if RUBY_VERSION < "1.9.1"
|
||||||
|
abort "Ace requires Ruby 1.9."
|
||||||
|
end
|
||||||
|
|
||||||
|
base = File.symlink?(__FILE__) ? File.readlink(__FILE__) : __FILE__
|
||||||
|
libdir = File.expand_path(File.join(File.dirname(base), "..", "lib"))
|
||||||
|
|
||||||
|
# because of system installation, there is bin/../lib, but not bin/../lib/ace
|
||||||
|
if File.directory?(File.join(libdir, "ace"))
|
||||||
|
$:.unshift(libdir) unless $:.include?(libdir)
|
||||||
|
end
|
||||||
|
|
||||||
|
require "ace"
|
||||||
|
require "ace/dsl"
|
||||||
|
|
||||||
|
if File.join(Dir.pwd, "boot.rb")
|
||||||
|
require File.join(Dir.pwd, "boot.rb")
|
||||||
|
else
|
||||||
|
abort "No boot.rb!"
|
||||||
|
end
|
||||||
|
|
||||||
|
if File.join(Dir.pwd, "rules.rb")
|
||||||
|
path = File.join(Dir.pwd, "rules.rb")
|
||||||
|
code = File.read(path)
|
||||||
|
rules = Ace::DSL.new
|
||||||
|
begin
|
||||||
|
rules.instance_eval(code)
|
||||||
|
rescue Exception => exception
|
||||||
|
puts "Error in DSL: #{exception.message}"
|
||||||
|
puts exception.backtrace
|
||||||
|
exit 1
|
||||||
|
end
|
||||||
|
else
|
||||||
|
abort "No rules.rb!"
|
||||||
|
end
|
||||||
|
|
||||||
|
rules.rules.each do |klass, files|
|
||||||
|
puts "#{klass} #{files.inspect}"
|
||||||
|
files.each do |file|
|
||||||
|
if File.binread(file).match(/^-{3,5}\s*$/)
|
||||||
|
raw_item = Ace::RawItem.new(file).tap(&:parse)
|
||||||
|
item = klass.create(raw_item.metadata, raw_item.content)
|
||||||
|
else
|
||||||
|
item = klass.create(Hash.new, File.read(file))
|
||||||
|
end
|
||||||
|
item.original_path = file
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
puts
|
||||||
|
|
||||||
|
rules.generators.each do |generator_klass|
|
||||||
|
puts "Running #{generator_klass}"
|
||||||
|
generator = generator_klass.new
|
||||||
|
begin
|
||||||
|
if generator.respond_to?(:run)
|
||||||
|
generator.run
|
||||||
|
else
|
||||||
|
abort "Generator #{generator.inspect} doesn't respond to the #run method!"
|
||||||
|
end
|
||||||
|
rescue Exception => exception
|
||||||
|
puts "Error in generator #{generator.inspect}: #{exception.message}"
|
||||||
|
puts exception.backtrace
|
||||||
|
exit 1
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
puts
|
||||||
|
|
||||||
|
Ace::Item.instances.each do |item|
|
||||||
|
puts "Generating #{item.output_path}"
|
||||||
|
item.save!
|
||||||
|
end
|
32
bin/ace-gen
Executable file
32
bin/ace-gen
Executable file
|
@ -0,0 +1,32 @@
|
||||||
|
#!/usr/bin/env ruby
|
||||||
|
# encoding: utf-8
|
||||||
|
|
||||||
|
if RUBY_VERSION < "1.9.1"
|
||||||
|
abort "Ace requires Ruby 1.9."
|
||||||
|
end
|
||||||
|
|
||||||
|
base = File.symlink?(__FILE__) ? File.readlink(__FILE__) : __FILE__
|
||||||
|
libdir = File.expand_path(File.join(File.dirname(base), "..", "lib"))
|
||||||
|
|
||||||
|
# because of system installation, there is bin/../lib, but not bin/../lib/ace
|
||||||
|
if File.directory?(File.join(libdir, "ace"))
|
||||||
|
$:.unshift(libdir) unless $:.include?(libdir)
|
||||||
|
end
|
||||||
|
|
||||||
|
begin
|
||||||
|
require "simple-templater"
|
||||||
|
rescue LoadError
|
||||||
|
abort "You have to install simple-templater first!"
|
||||||
|
end
|
||||||
|
|
||||||
|
begin
|
||||||
|
templater = SimpleTemplater.new(:ace)
|
||||||
|
generator = templater.find(:project)
|
||||||
|
generator.run(ARGV)
|
||||||
|
rescue SimpleTemplater::TargetAlreadyExist => exception
|
||||||
|
abort exception.message
|
||||||
|
rescue Interrupt
|
||||||
|
exit
|
||||||
|
rescue Exception => exception
|
||||||
|
abort "Exception #{exception.inspect} occured during running generator #{generator.inspect}\n#{exception.backtrace.join("\n")}"
|
||||||
|
end
|
20
example/app/posts.rb
Normal file
20
example/app/posts.rb
Normal file
|
@ -0,0 +1,20 @@
|
||||||
|
# encoding: utf-8
|
||||||
|
|
||||||
|
require "nokogiri"
|
||||||
|
require "ace/filters"
|
||||||
|
|
||||||
|
# Inheritted methods:
|
||||||
|
# - content
|
||||||
|
# - metadata
|
||||||
|
# - config
|
||||||
|
class Post < Ace::Item
|
||||||
|
before Ace::LayoutFilter, layout: "post.html"
|
||||||
|
|
||||||
|
def document
|
||||||
|
Nokogiri::HTML(self.content)
|
||||||
|
end
|
||||||
|
|
||||||
|
def excerpt
|
||||||
|
self.document.css("p.excerpt")
|
||||||
|
end
|
||||||
|
end
|
28
example/app/tags.rb
Normal file
28
example/app/tags.rb
Normal file
|
@ -0,0 +1,28 @@
|
||||||
|
# encoding: utf-8
|
||||||
|
|
||||||
|
class Tag < Ace::Item
|
||||||
|
before Ace::LayoutFilter, layout: "tag.html"
|
||||||
|
end
|
||||||
|
|
||||||
|
class TagPagesGenerator
|
||||||
|
def tags
|
||||||
|
Post.instances.inject(Hash.new) do |buffer, post|
|
||||||
|
if tags = post.metadata[:tags]
|
||||||
|
tags.each do |tag|
|
||||||
|
buffer[tag] ||= Array.new
|
||||||
|
buffer[tag] << post
|
||||||
|
end
|
||||||
|
end
|
||||||
|
buffer
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def run
|
||||||
|
self.tags.each do |tag_title, items|
|
||||||
|
tag_name = tag_title.downcase.gsub(" ", "-")
|
||||||
|
metadata = {title: tag_title, timestamp: Time.now}
|
||||||
|
tag = Tag.create(metadata, items)
|
||||||
|
tag.output_path = "output/tags/#{tag_name}.html"
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
6
example/boot.rb
Executable file
6
example/boot.rb
Executable file
|
@ -0,0 +1,6 @@
|
||||||
|
#!/usr/bin/env ace
|
||||||
|
# encoding: utf-8
|
||||||
|
|
||||||
|
Dir["app/**/*.rb"].each do |file|
|
||||||
|
load file
|
||||||
|
end
|
2
example/config.yml
Normal file
2
example/config.yml
Normal file
|
@ -0,0 +1,2 @@
|
||||||
|
title: ""
|
||||||
|
base_url: ""
|
1
example/content/assets/css/style.css
Normal file
1
example/content/assets/css/style.css
Normal file
|
@ -0,0 +1 @@
|
||||||
|
h1 { color: red; }
|
3
example/content/assets/js/application.js
Normal file
3
example/content/assets/js/application.js
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
window.onload = function () {
|
||||||
|
console.log("I don't do nothing really, I'm just pretending to be a useful asset.");
|
||||||
|
};
|
5
example/content/index.html.haml
Normal file
5
example/content/index.html.haml
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
- extends "base.html"
|
||||||
|
|
||||||
|
- Post.each do |post|
|
||||||
|
%h2= post.title
|
||||||
|
= post.excerpt
|
0
example/content/posts.json.rb
Normal file
0
example/content/posts.json.rb
Normal file
29
example/content/posts/node-js.html
Normal file
29
example/content/posts/node-js.html
Normal file
|
@ -0,0 +1,29 @@
|
||||||
|
---
|
||||||
|
title: Node.js Asynchronous JavaScript Framework
|
||||||
|
timestamp: 2010-09-16
|
||||||
|
tags: ["Development", "JavaScript", "Node.js"]
|
||||||
|
---
|
||||||
|
|
||||||
|
<p class="excerpt">
|
||||||
|
Node.js is an evented I/O framework for the V8 JavaScript engine. It is intended for writing scalable network programs such as web servers.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
Node.js is similar in purpose to Twisted for Python, Perl Object Environment for Perl, and EventMachine for Ruby. Unlike most JavaScript, it is not executed in a web browser, but it is rather related to server-side JavaScript. Node.js implements some CommonJS specifications[1]. Node.js includes a REPL environment for interactive testing.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<pre>
|
||||||
|
var sys = require('sys'),
|
||||||
|
http = require('http');
|
||||||
|
|
||||||
|
http.createServer(function (request, response) {
|
||||||
|
response.writeHead(200, {'Content-Type': 'text/plain'});
|
||||||
|
response.end('Hello World\n');
|
||||||
|
}).listen(8000);
|
||||||
|
|
||||||
|
sys.puts('Server running at http://127.0.0.1:8000/');
|
||||||
|
</pre>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
<em>From <a href="http://en.wikipedia.org/wiki/Node.js">Wikipedia.org</em>.
|
||||||
|
</p>
|
21
example/content/posts/ruby.html
Normal file
21
example/content/posts/ruby.html
Normal file
|
@ -0,0 +1,21 @@
|
||||||
|
---
|
||||||
|
title: Ruby Programming Language
|
||||||
|
timestamp: 2010-09-14
|
||||||
|
tags: ["Development", "Ruby"]
|
||||||
|
---
|
||||||
|
|
||||||
|
<p class="excerpt">
|
||||||
|
Ruby is a dynamic, reflective, general purpose object-oriented programming language that combines syntax inspired by Perl with Smalltalk-like features. Ruby originated in Japan during the mid-1990s and was first developed and designed by Yukihiro "Matz" Matsumoto. It was influenced primarily by Perl, Smalltalk, Eiffel, and Lisp.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
Ruby supports multiple programming paradigms, including functional, object oriented, imperative and reflective. It also has a dynamic type system and automatic memory management; it is therefore similar in varying respects to Python, Perl, Lisp, Dylan, Pike, and CLU.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
The standard 1.8.7 implementation is written in C, as a single-pass interpreted language. There is currently no specification of the Ruby language, so the original implementation is considered to be the de facto reference. As of 2010[update], there are a number of complete or upcoming alternative implementations of the Ruby language, including YARV, JRuby, Rubinius, IronRuby, MacRuby, and HotRuby, each of which takes a different approach, with IronRuby, JRuby and MacRuby providing just-in-time compilation and MacRuby also providing ahead-of-time compilation. The official 1.9 branch uses YARV, as will 2.0 (development), and will eventually supersede the slower Ruby MRI.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
<em>From <a href="http://en.wikipedia.org/wiki/Ruby_%28programming_language%29">Wikipedia.org</em>.
|
||||||
|
</p>
|
5
example/layouts/base.html.haml
Normal file
5
example/layouts/base.html.haml
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
!!!
|
||||||
|
%html
|
||||||
|
%head
|
||||||
|
%body
|
||||||
|
#main= block(:body)
|
5
example/layouts/post.html.haml
Normal file
5
example/layouts/post.html.haml
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
- extends "base.html"
|
||||||
|
|
||||||
|
- block(:body) do
|
||||||
|
%h1 My Coooooool Bloogiiiiseeeeek!
|
||||||
|
= item.content
|
6
example/layouts/tag.html.haml
Normal file
6
example/layouts/tag.html.haml
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
- extends "base.html"
|
||||||
|
|
||||||
|
- block(:body) do
|
||||||
|
%h1 My Coooooool Bloogiiiiseeeeek!
|
||||||
|
- item.content.each do |post|
|
||||||
|
= post.metadata[:title]
|
0
example/lib/initializer.rb
Normal file
0
example/lib/initializer.rb
Normal file
1
example/output/assets/css/style.css
Normal file
1
example/output/assets/css/style.css
Normal file
|
@ -0,0 +1 @@
|
||||||
|
h1 { color: red; }
|
3
example/output/assets/js/application.js
Normal file
3
example/output/assets/js/application.js
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
window.onload = function () {
|
||||||
|
console.log("I don't do nothing really, I'm just pretending to be a useful asset.");
|
||||||
|
};
|
32
example/output/posts/node-js.html
Normal file
32
example/output/posts/node-js.html
Normal file
|
@ -0,0 +1,32 @@
|
||||||
|
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
|
||||||
|
<html>
|
||||||
|
<head></head>
|
||||||
|
<body>
|
||||||
|
<div id='main'>
|
||||||
|
<h1>My Coooooool Bloogiiiiseeeeek!</h1>
|
||||||
|
<p class="excerpt">
|
||||||
|
Node.js is an evented I/O framework for the V8 JavaScript engine. It is intended for writing scalable network programs such as web servers.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
Node.js is similar in purpose to Twisted for Python, Perl Object Environment for Perl, and EventMachine for Ruby. Unlike most JavaScript, it is not executed in a web browser, but it is rather related to server-side JavaScript. Node.js implements some CommonJS specifications[1]. Node.js includes a REPL environment for interactive testing.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<pre>
|
||||||
|
var sys = require('sys'),
|
||||||
|
http = require('http');
|
||||||
|
|
||||||
|
http.createServer(function (request, response) {
|
||||||
|
response.writeHead(200, {'Content-Type': 'text/plain'});
|
||||||
|
response.end('Hello World\n');
|
||||||
|
}).listen(8000);
|
||||||
|
|
||||||
|
sys.puts('Server running at http://127.0.0.1:8000/');
|
||||||
|
</pre>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
<em>From <a href="http://en.wikipedia.org/wiki/Node.js">Wikipedia.org</em>.
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</body>
|
||||||
|
</html>
|
24
example/output/posts/ruby.html
Normal file
24
example/output/posts/ruby.html
Normal file
|
@ -0,0 +1,24 @@
|
||||||
|
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
|
||||||
|
<html>
|
||||||
|
<head></head>
|
||||||
|
<body>
|
||||||
|
<div id='main'>
|
||||||
|
<h1>My Coooooool Bloogiiiiseeeeek!</h1>
|
||||||
|
<p class="excerpt">
|
||||||
|
Ruby is a dynamic, reflective, general purpose object-oriented programming language that combines syntax inspired by Perl with Smalltalk-like features. Ruby originated in Japan during the mid-1990s and was first developed and designed by Yukihiro "Matz" Matsumoto. It was influenced primarily by Perl, Smalltalk, Eiffel, and Lisp.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
Ruby supports multiple programming paradigms, including functional, object oriented, imperative and reflective. It also has a dynamic type system and automatic memory management; it is therefore similar in varying respects to Python, Perl, Lisp, Dylan, Pike, and CLU.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
The standard 1.8.7 implementation is written in C, as a single-pass interpreted language. There is currently no specification of the Ruby language, so the original implementation is considered to be the de facto reference. As of 2010[update], there are a number of complete or upcoming alternative implementations of the Ruby language, including YARV, JRuby, Rubinius, IronRuby, MacRuby, and HotRuby, each of which takes a different approach, with IronRuby, JRuby and MacRuby providing just-in-time compilation and MacRuby also providing ahead-of-time compilation. The official 1.9 branch uses YARV, as will 2.0 (development), and will eventually supersede the slower Ruby MRI.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
<em>From <a href="http://en.wikipedia.org/wiki/Ruby_%28programming_language%29">Wikipedia.org</em>.
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</body>
|
||||||
|
</html>
|
10
example/output/posts/test.html
Normal file
10
example/output/posts/test.html
Normal file
|
@ -0,0 +1,10 @@
|
||||||
|
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
|
||||||
|
<html>
|
||||||
|
<head></head>
|
||||||
|
<body>
|
||||||
|
<div id='main'>
|
||||||
|
<h1>My Coooooool Bloogiiiiseeeeek!</h1>
|
||||||
|
content
|
||||||
|
</div>
|
||||||
|
</body>
|
||||||
|
</html>
|
11
example/output/tags/development.html
Normal file
11
example/output/tags/development.html
Normal file
|
@ -0,0 +1,11 @@
|
||||||
|
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
|
||||||
|
<html>
|
||||||
|
<head></head>
|
||||||
|
<body>
|
||||||
|
<div id='main'>
|
||||||
|
<h1>My Coooooool Bloogiiiiseeeeek!</h1>
|
||||||
|
Node.js Asynchronous JavaScript Framework
|
||||||
|
Ruby Programming Language
|
||||||
|
</div>
|
||||||
|
</body>
|
||||||
|
</html>
|
10
example/output/tags/javascript.html
Normal file
10
example/output/tags/javascript.html
Normal file
|
@ -0,0 +1,10 @@
|
||||||
|
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
|
||||||
|
<html>
|
||||||
|
<head></head>
|
||||||
|
<body>
|
||||||
|
<div id='main'>
|
||||||
|
<h1>My Coooooool Bloogiiiiseeeeek!</h1>
|
||||||
|
Node.js Asynchronous JavaScript Framework
|
||||||
|
</div>
|
||||||
|
</body>
|
||||||
|
</html>
|
10
example/output/tags/node.js.html
Normal file
10
example/output/tags/node.js.html
Normal file
|
@ -0,0 +1,10 @@
|
||||||
|
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
|
||||||
|
<html>
|
||||||
|
<head></head>
|
||||||
|
<body>
|
||||||
|
<div id='main'>
|
||||||
|
<h1>My Coooooool Bloogiiiiseeeeek!</h1>
|
||||||
|
Node.js Asynchronous JavaScript Framework
|
||||||
|
</div>
|
||||||
|
</body>
|
||||||
|
</html>
|
10
example/output/tags/ruby.html
Normal file
10
example/output/tags/ruby.html
Normal file
|
@ -0,0 +1,10 @@
|
||||||
|
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
|
||||||
|
<html>
|
||||||
|
<head></head>
|
||||||
|
<body>
|
||||||
|
<div id='main'>
|
||||||
|
<h1>My Coooooool Bloogiiiiseeeeek!</h1>
|
||||||
|
Ruby Programming Language
|
||||||
|
</div>
|
||||||
|
</body>
|
||||||
|
</html>
|
8
example/rules.rb
Normal file
8
example/rules.rb
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
# encoding: utf-8
|
||||||
|
|
||||||
|
# filters
|
||||||
|
rule Post, "posts/*.html"
|
||||||
|
rule Ace::Asset, "assets/**/*"
|
||||||
|
|
||||||
|
# generators
|
||||||
|
generator TagPagesGenerator#, "/tags/:slug"
|
0
example/tasks.rb
Executable file
0
example/tasks.rb
Executable file
130
lib/ace.rb
Normal file
130
lib/ace.rb
Normal file
|
@ -0,0 +1,130 @@
|
||||||
|
# encoding: utf-8
|
||||||
|
|
||||||
|
# === The boot process === #
|
||||||
|
# 1) load the app
|
||||||
|
# 2) load the rules (controllers / globs mapping)
|
||||||
|
# 3) load & instantiate all the renderable items
|
||||||
|
# 4) render all the items (here the filters & layouting run)
|
||||||
|
# 5) match the routes, write the files
|
||||||
|
|
||||||
|
require "yaml"
|
||||||
|
require "fileutils"
|
||||||
|
|
||||||
|
module Ace
|
||||||
|
class RawItem
|
||||||
|
attr_accessor :path, :metadata, :content
|
||||||
|
def initialize(path)
|
||||||
|
@data = File.read(path)
|
||||||
|
end
|
||||||
|
|
||||||
|
def parse
|
||||||
|
pieces = @data.split(/^-{3,5}\s*$/)
|
||||||
|
if pieces.size < 3
|
||||||
|
raise RuntimeError.new(
|
||||||
|
"The file '#{content_filename}' appears to start with a metadata section (three or five dashes at the top) but it does not seem to be in the correct format."
|
||||||
|
)
|
||||||
|
end
|
||||||
|
|
||||||
|
# Parse
|
||||||
|
self.metadata = YAML.load(pieces[1]).inject(Hash.new) { |metadata, pair| metadata.merge(pair[0].to_sym => pair[1]) } || Hash.new
|
||||||
|
self.content = pieces[2..-1].join.strip
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
# This class represents the items which will be
|
||||||
|
# eventually rendered like concrete posts, tags etc.
|
||||||
|
class Item
|
||||||
|
@@subclasses ||= Array.new
|
||||||
|
def self.inherited(subclass)
|
||||||
|
@@subclasses << subclass
|
||||||
|
end
|
||||||
|
|
||||||
|
@@instances ||= Array.new
|
||||||
|
def self.instances
|
||||||
|
@@instances
|
||||||
|
end
|
||||||
|
|
||||||
|
def self.before_filters
|
||||||
|
@before_filters ||= Array.new
|
||||||
|
end
|
||||||
|
|
||||||
|
def self.before(filter, *args)
|
||||||
|
self.before_filters << filter.new(*args)
|
||||||
|
end
|
||||||
|
|
||||||
|
def self.after_filters
|
||||||
|
@after_filters ||= Array.new
|
||||||
|
end
|
||||||
|
|
||||||
|
def self.after(filter, *args)
|
||||||
|
self.after_filters << filter.new(*args)
|
||||||
|
end
|
||||||
|
|
||||||
|
def self.create(metadata, content)
|
||||||
|
self.new(metadata, content).tap(&:register)
|
||||||
|
end
|
||||||
|
|
||||||
|
# Content can be anything, not just a string.
|
||||||
|
attr_accessor :metadata, :content
|
||||||
|
attr_accessor :original_path
|
||||||
|
def initialize(metadata, content)
|
||||||
|
@metadata = metadata
|
||||||
|
@content = content
|
||||||
|
end
|
||||||
|
|
||||||
|
def config
|
||||||
|
@config ||= begin
|
||||||
|
YAML::load_file("config.yml").inject(Hash.new) do |hash, pair|
|
||||||
|
hash.merge!(pair[0].to_sym => pair[1])
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def register
|
||||||
|
instances = self.class.instances
|
||||||
|
unless instances.include?(self)
|
||||||
|
self.class.instances << self
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def unregister
|
||||||
|
self.class.instances.delete(self)
|
||||||
|
end
|
||||||
|
|
||||||
|
def render
|
||||||
|
output = self.class.before_filters.inject(self.content) do |buffer, filter|
|
||||||
|
filter.call(self, buffer)
|
||||||
|
end
|
||||||
|
|
||||||
|
self.class.after_filters.inject(output) do |buffer, filter|
|
||||||
|
filter.call(self, buffer)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
attr_writer :output_path
|
||||||
|
def output_path
|
||||||
|
@output_path ||= begin
|
||||||
|
unless self.original_path.nil?
|
||||||
|
self.original_path.sub("content", "output")
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def save!
|
||||||
|
content = self.render.chomp # so filters can influence output_path
|
||||||
|
|
||||||
|
FileUtils.mkdir_p File.dirname(self.output_path)
|
||||||
|
File.open(self.output_path, "w") do |file|
|
||||||
|
file.puts content
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
class Asset < Item
|
||||||
|
end
|
||||||
|
|
||||||
|
module Helpers
|
||||||
|
def link_to(anchor, path_or_item, options = nil)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
21
lib/ace/dsl.rb
Normal file
21
lib/ace/dsl.rb
Normal file
|
@ -0,0 +1,21 @@
|
||||||
|
# encoding: utf-8
|
||||||
|
|
||||||
|
module Ace
|
||||||
|
class DSL
|
||||||
|
attr_accessor :rules, :generators
|
||||||
|
def initialize
|
||||||
|
@rules, @generators = Hash.new, Array.new
|
||||||
|
end
|
||||||
|
|
||||||
|
def rule(klass, *globs)
|
||||||
|
paths = globs.map { |glob| Dir.glob("content/#{glob}") }
|
||||||
|
files = paths.flatten.select { |path| File.file?(path) }
|
||||||
|
self.rules[klass] ||= Array.new
|
||||||
|
self.rules[klass].push(*files)
|
||||||
|
end
|
||||||
|
|
||||||
|
def generator(klass)
|
||||||
|
self.generators << klass
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
9
lib/ace/filters.rb
Normal file
9
lib/ace/filters.rb
Normal file
|
@ -0,0 +1,9 @@
|
||||||
|
# encoding: utf-8
|
||||||
|
|
||||||
|
module Ace
|
||||||
|
class Filter
|
||||||
|
def initialize(options = Hash.new)
|
||||||
|
@options = options
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
18
lib/ace/filters/haml.rb
Normal file
18
lib/ace/filters/haml.rb
Normal file
|
@ -0,0 +1,18 @@
|
||||||
|
# encoding: utf-8
|
||||||
|
|
||||||
|
require "haml"
|
||||||
|
require "ace/filters"
|
||||||
|
|
||||||
|
module Ace
|
||||||
|
class HamlFilter < Filter
|
||||||
|
# http://haml.hamptoncatlin.com/docs/rdoc/classes/Haml/Engine.html
|
||||||
|
def call(item, content)
|
||||||
|
if item.output_path && item.output_path.end_with?(".haml")
|
||||||
|
item.output_path.sub!(/\.haml$/, "")
|
||||||
|
end
|
||||||
|
|
||||||
|
engine = Haml::Engine.new(content)
|
||||||
|
engine.render(item.extend(Ace::Helpers))
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
19
lib/ace/filters/layout.rb
Normal file
19
lib/ace/filters/layout.rb
Normal file
|
@ -0,0 +1,19 @@
|
||||||
|
# encoding: utf-8
|
||||||
|
|
||||||
|
require "ace/filters"
|
||||||
|
require "template-inheritance"
|
||||||
|
|
||||||
|
TemplateInheritance::Template.paths << File.join(Dir.pwd, "layouts")
|
||||||
|
|
||||||
|
module Ace
|
||||||
|
class LayoutFilter < Filter
|
||||||
|
def initialize(options)
|
||||||
|
@path = options[:layout]
|
||||||
|
end
|
||||||
|
|
||||||
|
def call(item, content)
|
||||||
|
template = TemplateInheritance::Template.new(@path)
|
||||||
|
return template.render(item: item)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
5
lib/ace/version.rb
Normal file
5
lib/ace/version.rb
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
# encoding: utf-8
|
||||||
|
|
||||||
|
module Ace
|
||||||
|
VERSION = "0.0.1"
|
||||||
|
end
|
3
project_generator/metadata.yml
Normal file
3
project_generator/metadata.yml
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
---
|
||||||
|
:full: yes
|
||||||
|
:flat: no
|
9
project_generator/postprocess.rb
Normal file
9
project_generator/postprocess.rb
Normal file
|
@ -0,0 +1,9 @@
|
||||||
|
# encoding: utf-8
|
||||||
|
|
||||||
|
# This hook will be executed after templater finish in context of current generator object.
|
||||||
|
# Current directory is what you just generated, unless this is flat generator.
|
||||||
|
|
||||||
|
unless RUBY_PLATFORM.match(/mswin|mingw/)
|
||||||
|
sh "chmod +x boot.rb"
|
||||||
|
sh "chmod +x tasks.rb"
|
||||||
|
end
|
9
project_generator/setup.rb
Normal file
9
project_generator/setup.rb
Normal file
|
@ -0,0 +1,9 @@
|
||||||
|
# encoding: utf-8
|
||||||
|
|
||||||
|
# This hook will be executed in context of current generator object before templater start to generate new files.
|
||||||
|
# You can update context hash and register hooks. Don't forget to use merge! instead of merge, because you are
|
||||||
|
# manipulating with one object, rather than returning new one.
|
||||||
|
|
||||||
|
hook do |generator, context|
|
||||||
|
# TODO
|
||||||
|
end
|
6
simple-templater.scope
Normal file
6
simple-templater.scope
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
# encoding: utf-8
|
||||||
|
|
||||||
|
SimpleTemplater.scope(:ace) do
|
||||||
|
path = File.expand_path("../project_generator", __FILE__)
|
||||||
|
SimpleTemplater.register(:ace, :project, File.expand_path(path))
|
||||||
|
end
|
Loading…
Reference in a new issue