jgm-ecstatic 0.0.0

Sign up to get free protection for your applications and to get access to all the features.
data/ChangeLog ADDED
@@ -0,0 +1,3 @@
1
+ === 0.1 / 2009-07-19
2
+
3
+ * Initial release
data/README ADDED
@@ -0,0 +1,79 @@
1
+ = ecstatic
2
+
3
+ * http://github.com/jgm/ecstatic
4
+
5
+ == DESCRIPTION:
6
+
7
+ ecstatic helps you manage a static website. Pages are generated
8
+ from tenjin templates and YAML data files.
9
+
10
+ == FEATURES:
11
+
12
+ * Generates a static site, for high performance and security
13
+ * Separation of data and presentation, as in a dynamic web framework,
14
+ but with data in text files rather than databases
15
+ * Supports markdown
16
+ * Supports output in HTML, plain text, and LaTeX
17
+
18
+ == SYNOPSIS:
19
+
20
+ First, generate a site skeleton:
21
+
22
+ ecstatic mysite
23
+
24
+ See what has been done:
25
+
26
+ cd mysite
27
+ ls
28
+
29
+ To build the site (in the <tt>site</tt> directory):
30
+
31
+ rake
32
+
33
+ Try modifying the layout (<tt>standard.rbhtml</tt>),
34
+ the data (<tt>events.yaml</tt>), or the template
35
+ (<tt>events.rbhtml</tt>). Recompile the site with rake.
36
+
37
+ If you want to add new pages, just add templates and
38
+ datafiles, and register the pages in <tt>siteindex.yaml</tt>.
39
+ Put any static files in <tt>files</tt>; these will be copied
40
+ verbatim into the site.
41
+
42
+ If a page has no dynamic elements (other than the ones handled
43
+ by the layout), you can use a markdown file instead of a
44
+ template. Just give it the extension <tt>.markdown</tt>
45
+
46
+ == REQUIREMENTS:
47
+
48
+ * rpeg-markdown
49
+ * tenjin
50
+ * activesupport
51
+
52
+ == INSTALL:
53
+
54
+ * sudo gem install ecstatic
55
+
56
+ == LICENSE:
57
+
58
+ (The MIT License)
59
+
60
+ Copyright (c) 2009 John MacFarlane
61
+
62
+ Permission is hereby granted, free of charge, to any person obtaining
63
+ a copy of this software and associated documentation files (the
64
+ 'Software'), to deal in the Software without restriction, including
65
+ without limitation the rights to use, copy, modify, merge, publish,
66
+ distribute, sublicense, and/or sell copies of the Software, and to
67
+ permit persons to whom the Software is furnished to do so, subject to
68
+ the following conditions:
69
+
70
+ The above copyright notice and this permission notice shall be
71
+ included in all copies or substantial portions of the Software.
72
+
73
+ THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
74
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
75
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
76
+ IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
77
+ CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
78
+ TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
79
+ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/Rakefile ADDED
@@ -0,0 +1,26 @@
1
+ # -*- ruby -*-
2
+
3
+ require 'rubygems'
4
+
5
+ begin
6
+ require 'jeweler'
7
+ Jeweler::Tasks.new do |gemspec|
8
+ gemspec.name = "ecstatic"
9
+ gemspec.summary = "Framework for maintaining a static website from templates and data in YAML files."
10
+ gemspec.email = "jgm@berkeley.edu"
11
+ gemspec.homepage = "http://github.com/jgm/cloudlib"
12
+ gemspec.description = "Ecstatic is a framework for maintaining a static website from templates and data in YAML files."
13
+ gemspec.authors = ["John MacFarlane"]
14
+ gemspec.has_rdoc = true
15
+ gemspec.authors = ["John MacFarlane"]
16
+ gemspec.test_files = []
17
+ gemspec.add_dependency("activesupport", [">= 1.1"])
18
+ gemspec.add_dependency("rpeg-markdown", [">= 0.2"])
19
+ gemspec.add_dependency("tenjin", [">= 0.6.1"])
20
+ end
21
+ rescue LoadError
22
+ puts "Jeweler not available. Install it with: sudo gem install technicalpickles-jeweler -s http://gems.github.com"
23
+ end
24
+
25
+
26
+ # vim: syntax=ruby
data/VERSION ADDED
@@ -0,0 +1 @@
1
+ 0.0.0
data/bin/ecstatic ADDED
@@ -0,0 +1,19 @@
1
+ #!/usr/bin/env ruby
2
+ require 'fileutils'
3
+
4
+ if ARGV.length != 1
5
+ $stderr.puts "Usage: ecstatic PATH - create skeleton site in PATH\n"
6
+ exit 1
7
+ end
8
+
9
+ target = ARGV[0]
10
+
11
+ sampledir = File.join File.dirname(__FILE__), "../samplesite"
12
+ FileUtils.cp_r("#{sampledir}/.", target)
13
+
14
+ puts "Created skeleton in #{target}."
15
+ puts "To make your site:"
16
+ puts " cd #{target}"
17
+ puts " rake"
18
+
19
+ exit 0
data/ecstatic.gemspec ADDED
@@ -0,0 +1,62 @@
1
+ # -*- encoding: utf-8 -*-
2
+
3
+ Gem::Specification.new do |s|
4
+ s.name = %q{ecstatic}
5
+ s.version = "0.0.0"
6
+
7
+ s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
8
+ s.authors = ["John MacFarlane"]
9
+ s.date = %q{2009-07-20}
10
+ s.default_executable = %q{ecstatic}
11
+ s.description = %q{Ecstatic is a framework for maintaining a static website from templates and data in YAML files.}
12
+ s.email = %q{jgm@berkeley.edu}
13
+ s.executables = ["ecstatic"]
14
+ s.extra_rdoc_files = [
15
+ "ChangeLog",
16
+ "README"
17
+ ]
18
+ s.files = [
19
+ "ChangeLog",
20
+ "README",
21
+ "Rakefile",
22
+ "VERSION",
23
+ "bin/ecstatic",
24
+ "ecstatic.gemspec",
25
+ "lib/ecstatic.rb",
26
+ "samplesite/README",
27
+ "samplesite/Rakefile",
28
+ "samplesite/events.rbhtml",
29
+ "samplesite/events.yaml",
30
+ "samplesite/files/Ukulele.jpg",
31
+ "samplesite/files/css/print.css",
32
+ "samplesite/files/css/screen.css",
33
+ "samplesite/models/models.rb",
34
+ "samplesite/siteindex.yaml",
35
+ "samplesite/standard.rbhtml"
36
+ ]
37
+ s.has_rdoc = true
38
+ s.homepage = %q{http://github.com/jgm/cloudlib}
39
+ s.rdoc_options = ["--charset=UTF-8"]
40
+ s.require_paths = ["lib"]
41
+ s.rubygems_version = %q{1.3.1}
42
+ s.summary = %q{Framework for maintaining a static website from templates and data in YAML files.}
43
+
44
+ if s.respond_to? :specification_version then
45
+ current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
46
+ s.specification_version = 2
47
+
48
+ if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then
49
+ s.add_runtime_dependency(%q<activesupport>, [">= 1.1"])
50
+ s.add_runtime_dependency(%q<rpeg-markdown>, [">= 0.2"])
51
+ s.add_runtime_dependency(%q<tenjin>, [">= 0.6.1"])
52
+ else
53
+ s.add_dependency(%q<activesupport>, [">= 1.1"])
54
+ s.add_dependency(%q<rpeg-markdown>, [">= 0.2"])
55
+ s.add_dependency(%q<tenjin>, [">= 0.6.1"])
56
+ end
57
+ else
58
+ s.add_dependency(%q<activesupport>, [">= 1.1"])
59
+ s.add_dependency(%q<rpeg-markdown>, [">= 0.2"])
60
+ s.add_dependency(%q<tenjin>, [">= 0.6.1"])
61
+ end
62
+ end
data/lib/ecstatic.rb ADDED
@@ -0,0 +1,109 @@
1
+ require 'rubygems'
2
+ require 'tenjin'
3
+ require 'optparse'
4
+ require 'yaml'
5
+ require 'markdown'
6
+ require 'activesupport'
7
+
8
+ module Ecstatic
9
+ class Page
10
+ attr_accessor :contexthash, :layoutfile, :templatefile
11
+
12
+ def initialize(templatefile = nil, datafiles = [], layoutfile = nil)
13
+ @templatefile = templatefile
14
+ @layoutfile = layoutfile
15
+ # get context from data files
16
+ @contexthash = {}
17
+ datafiles.each do |file|
18
+ yamltext = File.open(file).read
19
+ yaml = YAML::load(yamltext)
20
+ # if YAML is not a hash, make a hash with file's basename as key:
21
+ unless yaml.class == Hash
22
+ yaml = {File.basename(file, File.extname(file)) => yaml}
23
+ end
24
+ yaml.each_pair do |key,val|
25
+ model = key.singularize.capitalize
26
+ begin
27
+ @contexthash[key] = Object.const_get(model).from_array(val)
28
+ rescue
29
+ $stderr.puts("Unable to initialize " + key + " from model " + model)
30
+ @contexthash[key] = val
31
+ end
32
+ end
33
+ end
34
+ end
35
+
36
+ def escapefun(format)
37
+ case
38
+ when format == :html
39
+ return 'Ecstatic.markdown_to_compact_html'
40
+ when format == :latex
41
+ return 'Ecstatic.markdown_to_latex'
42
+ else
43
+ return 'escape'
44
+ end
45
+ end
46
+
47
+ def to_format(format)
48
+ engine = Tenjin::Engine.new(:cache => false, :escapefunc => escapefun(format))
49
+
50
+ if File.extname(self.templatefile) == '.markdown'
51
+ contents = File.open(self.templatefile).read
52
+ output = case
53
+ when format == :html
54
+ markdown_to_compact_html(contents)
55
+ when format == :latex
56
+ markdown_to_latex(contents)
57
+ else
58
+ escape(contents)
59
+ end
60
+ else
61
+ context = Tenjin::Context.new(self.contexthash)
62
+ output = engine.render(self.templatefile, context)
63
+ end
64
+
65
+ if self.layoutfile
66
+ supercontext = Tenjin::Context.new({'_contents' => output})
67
+ superoutput = engine.render(self.layoutfile, {'_contents' => output})
68
+ return superoutput
69
+ else
70
+ return output
71
+ end
72
+ end
73
+
74
+ def to_html
75
+ self.to_format(:html)
76
+ end
77
+
78
+ def to_latex
79
+ self.to_format(:latex)
80
+ end
81
+
82
+ def to_plain
83
+ self.to_format(:plain)
84
+ end
85
+ end
86
+
87
+ # escape functions
88
+
89
+ def markdown_to_html(str)
90
+ Markdown.new(str, :smart).to_html
91
+ end
92
+
93
+ def markdown_to_compact_html(str)
94
+ res = markdown_to_html(str)
95
+ if (res =~ /<p>.*<p>/)
96
+ return res
97
+ else # only one paragraph
98
+ return res.gsub(/<\/?p>/,"")
99
+ end
100
+ end
101
+
102
+ def markdown_to_latex(str)
103
+ Markdown.new(str, :smart).to_latex
104
+ end
105
+
106
+ alias m markdown_to_html
107
+ module_function :markdown_to_html, :markdown_to_compact_html, :markdown_to_latex, :m
108
+ end
109
+
data/samplesite/README ADDED
@@ -0,0 +1 @@
1
+ To be completed.
@@ -0,0 +1,66 @@
1
+ require 'rake/clean'
2
+ require 'ecstatic'
3
+ require 'find'
4
+
5
+ # load user-defined data models
6
+ Find.find('models') do |f|
7
+ require f unless f == 'models'
8
+ end
9
+
10
+ SITEDIR = "site"
11
+ CLEAN.include(SITEDIR)
12
+
13
+ LAYOUT = "standard.rbhtml"
14
+
15
+ siteindex = YAML::load File.read("siteindex.yaml")
16
+ SITETITLE = siteindex['sitetitle']
17
+
18
+ # construct list of pages
19
+ PAGES = {}
20
+ siteindex['pages'].each do |p|
21
+ dest = File.join SITEDIR, p['url']
22
+ PAGES[dest] = {
23
+ :title => p['title'],
24
+ :template => p['template'],
25
+ :data => if p['data'].class == Array
26
+ p['data']
27
+ elsif p['data'].class == String
28
+ [p['data']]
29
+ else
30
+ []
31
+ end }
32
+ end
33
+
34
+ # construct hash of files
35
+ FILESDIR = "files"
36
+ FILES = {}
37
+ Find.find(FILESDIR) do |f|
38
+ if f != FILESDIR
39
+ base = f.gsub(/^[^\/]*\//,"")
40
+ FILES[File.join(SITEDIR, base)] = f
41
+ end
42
+ end
43
+
44
+ task :default => :all
45
+ task :all => [SITEDIR] + PAGES.keys + FILES.keys
46
+
47
+ directory SITEDIR
48
+
49
+ FILES.each_pair do |dest,src|
50
+ file dest => src do
51
+ d = File.dirname dest
52
+ if ! File.exists? d
53
+ mkdir_p(File.dirname(dest))
54
+ end
55
+ cp src, dest
56
+ end
57
+ end
58
+
59
+ PAGES.each_pair do |dest,page|
60
+
61
+ file dest => ([page[:template], LAYOUT] + page[:data]) do
62
+ output = Ecstatic::Page.new(page[:template], page[:data], LAYOUT).to_html
63
+ File.open(dest, 'w').write(output)
64
+ end
65
+
66
+ end
@@ -0,0 +1,9 @@
1
+ <h1>Events</h1>
2
+ <img src="Ukulele.jpg"/>
3
+ <ul>
4
+ <?rb for event in @events.sort_by {|e| e.date}.reverse ?>
5
+ <li>
6
+ ${event.speaker}, ${event.title} (${event.date.to_s("%B %d, %Y")})
7
+ </li>
8
+ <?rb end ?>
9
+ </ul>
@@ -0,0 +1,14 @@
1
+ events:
2
+
3
+ - title: Why Static Sites Are Best
4
+ speaker: Sam Spade
5
+ date:
6
+ start: 2009-04-08
7
+ end : 2009-04-09
8
+
9
+ - title: Ruby vs. Haskell
10
+ speaker:
11
+ - Sam Spade
12
+ - John Doe
13
+ date: 2009-05-09
14
+
Binary file
@@ -0,0 +1 @@
1
+ /* CSS for printing here */
@@ -0,0 +1 @@
1
+ /* CSS for screen display here */
@@ -0,0 +1,58 @@
1
+ class Array
2
+ def to_s
3
+ self.to_sentence
4
+ end
5
+ end
6
+
7
+ class Model
8
+ def modelname
9
+ self.class.lowercase
10
+ end
11
+ def self.from_array(ary)
12
+ return ary.map do |t|
13
+ self.new(t)
14
+ end
15
+ end
16
+ end
17
+
18
+ class Daterange < Model
19
+ attr_accessor :start, :end
20
+
21
+ def initialize(d)
22
+ if d.class == Hash
23
+ @start = d['start']
24
+ @end = d['end']
25
+ else
26
+ @start = d
27
+ @end = nil
28
+ end
29
+ end
30
+
31
+ def to_s(format="%F")
32
+ if self.end
33
+ return(self.start.strftime(format) + " - " + self.end.strftime(format))
34
+ else
35
+ return self.start.strftime(format)
36
+ end
37
+ end
38
+
39
+ def <=>(b)
40
+ if self.end && b.end
41
+ [self.start, self.end] <=> [b.start, b.end]
42
+ else
43
+ self.start <=> b.start
44
+ end
45
+ end
46
+
47
+ end
48
+
49
+ class Event < Model
50
+ attr_accessor :title, :date, :speaker
51
+
52
+ def initialize(e)
53
+ @title = e['title']
54
+ @date = Daterange.new(e['date'])
55
+ @speaker = e['speaker']
56
+ end
57
+ end
58
+
@@ -0,0 +1,12 @@
1
+ sitetitle: My ecstatic site
2
+
3
+ pages:
4
+
5
+ - url: events.html
6
+ title: Events
7
+ template: events.rbhtml
8
+ data: events.yaml
9
+
10
+ menu:
11
+
12
+ - events.html
@@ -0,0 +1,10 @@
1
+ <html>
2
+ <head>
3
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
4
+ <link rel="stylesheet" type="text/css" href="css/screen.css" />
5
+ <link rel="stylesheet" type="text/css" media="print" href="css/print.css" />
6
+ </head>
7
+ <body>
8
+ #{@_contents}
9
+ </body>
10
+ </html>
metadata ADDED
@@ -0,0 +1,99 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: jgm-ecstatic
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.0
5
+ platform: ruby
6
+ authors:
7
+ - John MacFarlane
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+
12
+ date: 2009-07-20 00:00:00 -07:00
13
+ default_executable: ecstatic
14
+ dependencies:
15
+ - !ruby/object:Gem::Dependency
16
+ name: activesupport
17
+ type: :runtime
18
+ version_requirement:
19
+ version_requirements: !ruby/object:Gem::Requirement
20
+ requirements:
21
+ - - ">="
22
+ - !ruby/object:Gem::Version
23
+ version: "1.1"
24
+ version:
25
+ - !ruby/object:Gem::Dependency
26
+ name: rpeg-markdown
27
+ type: :runtime
28
+ version_requirement:
29
+ version_requirements: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: "0.2"
34
+ version:
35
+ - !ruby/object:Gem::Dependency
36
+ name: tenjin
37
+ type: :runtime
38
+ version_requirement:
39
+ version_requirements: !ruby/object:Gem::Requirement
40
+ requirements:
41
+ - - ">="
42
+ - !ruby/object:Gem::Version
43
+ version: 0.6.1
44
+ version:
45
+ description: Ecstatic is a framework for maintaining a static website from templates and data in YAML files.
46
+ email: jgm@berkeley.edu
47
+ executables:
48
+ - ecstatic
49
+ extensions: []
50
+
51
+ extra_rdoc_files:
52
+ - ChangeLog
53
+ - README
54
+ files:
55
+ - ChangeLog
56
+ - README
57
+ - Rakefile
58
+ - VERSION
59
+ - bin/ecstatic
60
+ - ecstatic.gemspec
61
+ - lib/ecstatic.rb
62
+ - samplesite/README
63
+ - samplesite/Rakefile
64
+ - samplesite/events.rbhtml
65
+ - samplesite/events.yaml
66
+ - samplesite/files/Ukulele.jpg
67
+ - samplesite/files/css/print.css
68
+ - samplesite/files/css/screen.css
69
+ - samplesite/models/models.rb
70
+ - samplesite/siteindex.yaml
71
+ - samplesite/standard.rbhtml
72
+ has_rdoc: true
73
+ homepage: http://github.com/jgm/cloudlib
74
+ post_install_message:
75
+ rdoc_options:
76
+ - --charset=UTF-8
77
+ require_paths:
78
+ - lib
79
+ required_ruby_version: !ruby/object:Gem::Requirement
80
+ requirements:
81
+ - - ">="
82
+ - !ruby/object:Gem::Version
83
+ version: "0"
84
+ version:
85
+ required_rubygems_version: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - ">="
88
+ - !ruby/object:Gem::Version
89
+ version: "0"
90
+ version:
91
+ requirements: []
92
+
93
+ rubyforge_project:
94
+ rubygems_version: 1.2.0
95
+ signing_key:
96
+ specification_version: 2
97
+ summary: Framework for maintaining a static website from templates and data in YAML files.
98
+ test_files: []
99
+