jgm-ecstatic 0.0.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/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
+