mango 0.1.1 → 0.5.0.beta1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (74) hide show
  1. data/.gitignore +6 -0
  2. data/.yardopts +6 -0
  3. data/README.mdown +62 -29
  4. data/Rakefile +62 -0
  5. data/VERSION +1 -0
  6. data/bin/mango +5 -0
  7. data/doc/HISTORY.mdown +71 -0
  8. data/doc/ROAD-MAP.mdown +10 -0
  9. data/lib/mango.rb +7 -0
  10. data/lib/mango/application.rb +334 -0
  11. data/lib/mango/content_page.rb +193 -0
  12. data/lib/mango/dependencies.rb +125 -0
  13. data/lib/mango/flavored_markdown.rb +82 -0
  14. data/lib/mango/rack/debugger.rb +22 -0
  15. data/lib/mango/runner.rb +95 -0
  16. data/lib/mango/templates/Gemfile +4 -0
  17. data/lib/mango/templates/README.md +1 -0
  18. data/lib/mango/templates/config.ru +4 -0
  19. data/lib/mango/templates/content/index.md +5 -0
  20. data/lib/mango/templates/themes/default/public/images/particles.gif +0 -0
  21. data/lib/mango/templates/themes/default/public/javascripts/fireworks.js +546 -0
  22. data/lib/mango/templates/themes/default/public/javascripts/timer.js +5 -0
  23. data/lib/mango/templates/themes/default/public/robots.txt +5 -0
  24. data/lib/mango/templates/themes/default/public/styles/fireworks.css +55 -0
  25. data/lib/mango/templates/themes/default/public/styles/reset.css +54 -0
  26. data/lib/mango/templates/themes/default/styles/screen.sass +17 -0
  27. data/lib/mango/templates/themes/default/views/404.haml +21 -0
  28. data/lib/mango/templates/themes/default/views/layout.haml +20 -0
  29. data/lib/mango/templates/themes/default/views/page.haml +3 -0
  30. data/lib/mango/version.rb +6 -0
  31. data/mango.gemspec +35 -0
  32. data/spec/app_root/content/about/index.haml +1 -0
  33. data/spec/app_root/content/about/us.haml +1 -0
  34. data/spec/app_root/content/engines/haml.haml +7 -0
  35. data/spec/app_root/content/engines/markdown.markdown +7 -0
  36. data/spec/app_root/content/engines/md.md +7 -0
  37. data/spec/app_root/content/engines/mdown.mdown +7 -0
  38. data/spec/app_root/content/index.haml +1 -0
  39. data/spec/app_root/content/override.haml +1 -0
  40. data/spec/app_root/content/page_with_missing_view.haml +4 -0
  41. data/spec/app_root/content/turner+hooch.haml +1 -0
  42. data/spec/app_root/security_hole.haml +1 -0
  43. data/spec/app_root/themes/default/public/default.css +3 -0
  44. data/spec/app_root/themes/default/public/images/index.html +10 -0
  45. data/spec/app_root/themes/default/public/images/ripe-mango.jpg +0 -0
  46. data/spec/app_root/themes/default/public/override +10 -0
  47. data/spec/app_root/themes/default/public/robots.txt +2 -0
  48. data/spec/app_root/themes/default/public/styles/override.css +3 -0
  49. data/spec/app_root/themes/default/public/styles/reset.css +27 -0
  50. data/spec/app_root/themes/default/public/styles/subfolder/another.css +3 -0
  51. data/spec/app_root/themes/default/security_hole.sass +1 -0
  52. data/spec/app_root/themes/default/security_hole.txt +1 -0
  53. data/spec/app_root/themes/default/styles/override.sass +2 -0
  54. data/spec/app_root/themes/default/styles/screen.sass +13 -0
  55. data/spec/app_root/themes/default/styles/subfolder/screen.sass +12 -0
  56. data/spec/app_root/themes/default/views/404.haml +7 -0
  57. data/spec/app_root/themes/default/views/layout.haml +7 -0
  58. data/spec/app_root/themes/default/views/page.haml +4 -0
  59. data/spec/mango/application/routing_content_pages_spec.rb +357 -0
  60. data/spec/mango/application/routing_public_files_spec.rb +181 -0
  61. data/spec/mango/application/routing_style_sheets_spec.rb +286 -0
  62. data/spec/mango/application_spec.rb +34 -0
  63. data/spec/mango/content_page/finding_spec.rb +213 -0
  64. data/spec/mango/content_page/initializing_spec.rb +298 -0
  65. data/spec/mango/content_page_spec.rb +44 -0
  66. data/spec/mango/dependencies_spec.rb +189 -0
  67. data/spec/mango/flavored_markdown_spec.rb +52 -0
  68. data/spec/mango/rack/debugger_spec.rb +114 -0
  69. data/spec/mango/version_spec.rb +18 -0
  70. data/spec/quality_spec.rb +32 -0
  71. data/spec/spec.opts +3 -0
  72. data/spec/spec_helper.rb +18 -0
  73. data/spec/support/matchers/malformed_whitespace_matchers.rb +60 -0
  74. metadata +304 -17
@@ -0,0 +1,193 @@
1
+ # encoding: UTF-8
2
+
3
+ require "bluecloth"
4
+ require "haml"
5
+ require "yaml"
6
+
7
+ module Mango
8
+ # `ContentPage` is a **model** class. An instance of `ContentPage` is the representation of a
9
+ # single content file. The primary responsiblity of `ContentPage` is to manage the conversion of
10
+ # user-generated data into HTML. It accomplishes this task by utilizing 3rd-party content
11
+ # engines, which convert easy-to-read, easy-to-write plain text and markup into structurally
12
+ # valid HTML.
13
+ #
14
+ # `ContentPage` instances have two primary components -- **a body** and some **attributes**.
15
+ # Each component is defined within a single content file.
16
+ #
17
+ # ### Example content file
18
+ #
19
+ # # mango_poem.markdown
20
+ # ---
21
+ # title: The Sin of Mango
22
+ # categories:
23
+ # - bad
24
+ # - poetry
25
+ # ---
26
+ # Mango is like a drug.
27
+ # You must have more and more and more of the Mango
28
+ # until there is no Mango left.
29
+ # Not even for Mango!
30
+ #
31
+ # Mangos aside, let's bring attention to a few important facets of this example and content files
32
+ # in general.
33
+ #
34
+ # 1. Content pages are stored as files on disk. Here, the file name is `mango_poem.markdown`.
35
+ # 2. Attributes are defined first, embedded within triple-dashed ("---") dividers.
36
+ # 3. The body comes second, nestled comfortably below the attributes header.
37
+ # 4. Attributes are key-value pairs, defined with [YAML](http://www.yaml.org/) formatting.
38
+ # 5. The body, in this example, is plain-text. Because of the file extension, it's interpretted
39
+ # as Markdown.
40
+ #
41
+ # ### The Body
42
+ #
43
+ # The body of a content file may be written using one of the following human-friendly formats:
44
+ #
45
+ # * [Markdown](http://daringfireball.net/projects/markdown/syntax) extended with
46
+ # `Mango::FlavoredMarkdown`
47
+ # * [Haml](http://haml-lang.com/)
48
+ #
49
+ # The content file's extension determines the body's formatting. For a complete list of content
50
+ # file formats and their extensions, see `Mango::ContentPage::CONTENT_ENGINES`
51
+ #
52
+ # `ContentPage` instances are expected to be passed along into the view template they define.
53
+ # Once in that scope, the instance can convert its body to HTML with the `#to_html` method:
54
+ #
55
+ # @content_page.to_html
56
+ #
57
+ # ### The Attributes
58
+ #
59
+ # Attributes are key-value pairs, defined with [YAML](http://www.yaml.org/) formatting.
60
+ #
61
+ # All `ContentPage` instances have a `view` attribute, even if one is not explicitly declared in
62
+ # the content file. This attribute is essential as it guides the `Mango::Application` to render
63
+ # the correct view template file.
64
+ #
65
+ # When declaring an explicit view template, only the base file name is important. **It's assumed
66
+ # that all view templates are in Haml format.** The default view template file name is defined
67
+ # by `Mango::ContentPage::DEFAULT["attributes"]`.
68
+ #
69
+ # Syntactic sugar has been added for accessing attribtues. For example:
70
+ #
71
+ # @content_page.attributes["title"]
72
+ #
73
+ # can be shortened to
74
+ #
75
+ # @content_page.title
76
+ #
77
+ # Again, `ContentPage` instances are expected to be passed along into the view template they
78
+ # define. With a `@content_page` instance in scope, accessing attributes inside a Haml template
79
+ # works like this:
80
+ #
81
+ # %title
82
+ # = @content_page.title
83
+ #
84
+ # @see Mango::FlavoredMarkdown
85
+ #
86
+ class ContentPage
87
+ class PageNotFound < RuntimeError; end
88
+
89
+ # Known content formats and their associated file extensions
90
+ CONTENT_ENGINES = {
91
+ :markdown => ["md", "mdown", "markdown"],
92
+ :haml => ["haml"]
93
+ }
94
+
95
+ # Default values for various accessors
96
+ DEFAULT = {
97
+ :attributes => { "view" => :page },
98
+ :body => "",
99
+ :content_engine => :markdown
100
+ }
101
+
102
+ # `String`
103
+ attr_reader :data
104
+ # `Hash`
105
+ attr_reader :attributes
106
+ # `String`
107
+ attr_reader :body
108
+ # `Symbol`
109
+ attr_reader :content_engine
110
+
111
+ # Creates a new instance by extracting the body and attributes from raw data. Any extracted
112
+ # components found are merged with their defaults.
113
+ #
114
+ # @param [String] data
115
+ # @param [Hash] options
116
+ # @option options [Symbol] :content_engine See `CONTENT_ENGINES` and `DEFAULT[:content_engine]`
117
+ #
118
+ def initialize(data, options = {})
119
+ @data = data
120
+ @content_engine = options.delete(:content_engine) || DEFAULT[:content_engine]
121
+
122
+ if self.data =~ /^(---\s*\n.*?\n?)^(---\s*$\n?)/m
123
+ @attributes = DEFAULT[:attributes].merge(YAML.load($1) || {})
124
+ @body = self.data[($1.size + $2.size)..-1]
125
+ else
126
+ @attributes = DEFAULT[:attributes]
127
+ @body = self.data || DEFAULT[:body]
128
+ end
129
+ end
130
+
131
+ # Create a new instance by searching for and reading a content file from disk. Content files
132
+ # are searched consecutively until a page with known content extension is found.
133
+ #
134
+ # @param [String] path_without_extension
135
+ # @raise [PageNotFound] Raised when a content page cannot be found
136
+ # @return [ContentPage] A new instance is created and returned when found
137
+ #
138
+ def self.find_by_path(path_without_extension)
139
+ CONTENT_ENGINES.each_pair do |content_engine, extensions|
140
+ extensions.each do |extension|
141
+ path = "#{path_without_extension}.#{extension}"
142
+ return new(File.read(path), :content_engine => content_engine) if File.exist?(path)
143
+ end
144
+ end
145
+
146
+ raise PageNotFound, "Unable to find content page for path -- #{path_without_extension}"
147
+ end
148
+
149
+ # Given a content engine, converts the body to HTML.
150
+ #
151
+ # @raise [RuntimeError] Raised when content engine is unknown
152
+ # @return [String] HTML from the conversion
153
+ #
154
+ def to_html
155
+ case content_engine
156
+ when :markdown
157
+ BlueCloth.new(Mango::FlavoredMarkdown.shake(body)).to_html
158
+ when :haml
159
+ Haml::Engine.new(body).to_html
160
+ else
161
+ raise "Unknown content engine -- #{content_engine}"
162
+ end
163
+ end
164
+
165
+ # Returns just the view template's base file name. It's assumed that all view templates are in
166
+ # Haml format.
167
+ #
168
+ # @example
169
+ # @content_page.attributes["view"] #=> "blog.haml"
170
+ # @content_page.view #=> :blog
171
+ #
172
+ # @return [Symbol] The view template's base file name.
173
+ #
174
+ def view
175
+ File.basename(attributes["view"], '.*').to_sym
176
+ end
177
+
178
+ # Adds syntactic suger for reading attributes.
179
+ #
180
+ # @example
181
+ # @content_page.title == @content_page.attributes["title"]
182
+ #
183
+ # @param [Symbol] method_name
184
+ # @raise [NoMethodError] Raised when there is no method name key in attributes
185
+ # @return [Object] Value of the method name attribute
186
+ #
187
+ def method_missing(method_name)
188
+ key = method_name.to_s
189
+ attributes.has_key?(key) ? attributes[key] : super
190
+ end
191
+
192
+ end
193
+ end
@@ -0,0 +1,125 @@
1
+ # encoding: UTF-8
2
+
3
+ module Mango
4
+ # `Mango::Dependencies` is a class-methods-only **singleton** class that performs both strict
5
+ # parse-time dependency checking and simple, elegant run-time dependency warning.
6
+ #
7
+ # My preferred mental model is to consider software library dependencies as a snapshot in time.
8
+ # I also make the assumption, sometimes incorrectly, that a newer version of a software library
9
+ # is not always a better version.
10
+ #
11
+ # `Mango::Dependencies` automatically enforces a strict parse-time check for the
12
+ # `REQUIRED_RUBY_VERSION` on both application and development processes for the `Mango` library.
13
+ # (i.e. `bin/mango`, `rake`, `spec`, etc) Because of this, I've ensured this file is
14
+ # syntactically compatible with Ruby 1.8.6 or higher.
15
+ #
16
+ # Currently, `Mango` does **not** enforce strict parse-time version checking on `DEVELOPMENT_GEMS`.
17
+ # In the future, I would like to experiment with using RubyGems and the `Kernel#gem` method to
18
+ # this end. For now, each developer is responsible for ensuring the correct versions of their
19
+ # necessary development gems are located in the `$LOAD_PATH` on their system.
20
+ #
21
+ # When a gem is required, but a `LoadError` is raised, and rescued, `Mango::Dependencies` can be
22
+ # incorporated into the process to warn a developer of missing development features. Even with a
23
+ # few methods -- `.create_warning_for` and `.warn_at_exit` -- users are automatically warned, in
24
+ # this case at the moment of termination, about gems that could not found be in the `$LOAD_PATH`.
25
+ # Using `Mango::Dependencies` is **not** a mandatory inclusion for all gem requirements, merely a
26
+ # guide to help developers quickly see obstacles in their path.
27
+ #
28
+ # @example Simple usage with the YARD gem
29
+ # begin
30
+ # require "yard"
31
+ # YARD::Rake::YardocTask.new(:yard)
32
+ # rescue LoadError => e
33
+ # Mango::Dependencies.create_warning_for(e)
34
+ # end
35
+ #
36
+ # @see Mango::Dependencies.create_warning_for
37
+ # @see Mango::Dependencies.warn_at_exit
38
+ class Dependencies
39
+ # For now, starting with Ruby 1.9.1 but I would like to experiment with compatibility with Ruby >= 1.9.1 in the future.
40
+ REQUIRED_RUBY_VERSION = "1.9.1"
41
+
42
+ # bluecloth is a hidden yard dependency for markdown support
43
+ DEVELOPMENT_GEMS = {
44
+ :"rack-test" => "0.5.4",
45
+ :rspec => "1.3.0",
46
+ :yard => "0.5.8",
47
+ :"yard-sinatra" => "0.5.0",
48
+ :bluecloth => "2.0.7"
49
+ }
50
+
51
+ FILE_NAME_TO_GEM_NAME = {
52
+ :"rack/test" => :"rack-test",
53
+ :"spec/rake/spectask" => :rspec,
54
+ :"yard/sinatra" => :"yard-sinatra"
55
+ }
56
+
57
+ # Empties the warnings cache. This method is called when the class is required.
58
+ def self.destroy_warnings
59
+ @@warnings_cache = []
60
+ end
61
+ destroy_warnings
62
+
63
+ # Creates and caches a warning from a `LoadError` exception. Warnings are only created for
64
+ # known development gem dependencies.
65
+ #
66
+ # @param [LoadError] error A rescued exception
67
+ # @raise [RuntimeError] Raised when the `LoadError` argument is an unknown development gem.
68
+ def self.create_warning_for(error)
69
+ pattern = %r{no such file to load -- ([\w\-\\/]*)}
70
+ error.message.match(pattern) do |match_data|
71
+ file_name = match_data[1].to_sym
72
+ gem_name = if DEVELOPMENT_GEMS.has_key?(file_name)
73
+ file_name
74
+ elsif FILE_NAME_TO_GEM_NAME.has_key?(file_name)
75
+ FILE_NAME_TO_GEM_NAME[file_name]
76
+ else
77
+ raise "Cannot create a dependency warning for unknown development gem -- #{file_name}"
78
+ end
79
+
80
+ @@warnings_cache << "#{gem_name} --version '#{DEVELOPMENT_GEMS[gem_name]}'"
81
+ end
82
+ end
83
+
84
+ # Displays a warning message to the user on the standard output channel if there are warnings
85
+ # to render.
86
+ #
87
+ # @example Sample warning message
88
+ # The following development gem dependencies could not be found. Without them, some available development features are missing:
89
+ # jeweler --version "1.4.0"
90
+ # rspec --version "1.3.0"
91
+ # yard --version "0.5.3"
92
+ # bluecloth --version "2.0.7"
93
+ def self.render_warnings
94
+ unless @@warnings_cache.empty?
95
+ message = []
96
+ message << "The following development gem dependencies could not be found. Without them, some available development features are missing:"
97
+ message += @@warnings_cache
98
+ puts "\n" + message.join("\n")
99
+ end
100
+ end
101
+
102
+ # Attaches a call to `render_warnings` to `Kernel#at_exit`
103
+ def self.warn_at_exit
104
+ at_exit { render_warnings }
105
+ end
106
+
107
+ private
108
+
109
+ # Checks that the version of the current Ruby process matches the `REQUIRED_RUBY_VERSION`.
110
+ # This method is automatically invoked at the first time this class is required, ensuring the
111
+ # correct Ruby version at parse-time.
112
+ #
113
+ # @param [String] ruby_version Useful for automated specifications. Defaults to `RUBY_VERSION`.
114
+ # @raise [SystemExit] Raised, with a message, when the process is using an incorrect version of Ruby.
115
+ def self.check_ruby_version(ruby_version = RUBY_VERSION)
116
+ unless ruby_version == REQUIRED_RUBY_VERSION
117
+ abort <<-ERROR
118
+ This library requires Ruby #{REQUIRED_RUBY_VERSION}, but you're using #{ruby_version}.
119
+ Please visit http://www.ruby-lang.org/ for installation instructions.
120
+ ERROR
121
+ end
122
+ end
123
+ check_ruby_version
124
+ end
125
+ end
@@ -0,0 +1,82 @@
1
+ require "digest/md5"
2
+
3
+ module Mango
4
+ # `Mango::FlavoredMarkdown` (MFM) is a subset of GithubFlavoredMarkdown (GFM). MFM adds a touch
5
+ # seasoning to the standard Markdown (SM) syntax.
6
+ #
7
+ # ## Differences from standard Markdown
8
+ #
9
+ # ### Newlines
10
+ #
11
+ # The biggest difference that MFM introduces is in the handling of linebreaks. With SM you can
12
+ # hard wrap paragraphs of text and they will be combined into a single paragraph. I find this to
13
+ # be the cause of a huge number of unintentional formatting errors. MFM treats newlines in
14
+ # paragraph-like content as real line breaks, which is probably what you intended.
15
+ #
16
+ # The next paragraph contains two phrases separated by a single newline character:
17
+ #
18
+ # Roses are red
19
+ # Violets are blue
20
+ #
21
+ # becomes
22
+ #
23
+ # Roses are red
24
+ # Violets are blue
25
+ #
26
+ # ### Multiple underscores in words
27
+ #
28
+ # It is not reasonable to italicize just part of a word, especially when you're dealing with code
29
+ # and names often appear with multiple underscores. Therefore, MFM ignores multiple underscores
30
+ # in words.
31
+ #
32
+ # perform_complicated_task
33
+ # do_this_and_do_that_and_another_thing
34
+ #
35
+ # becomes
36
+ #
37
+ # perform_complicated_task
38
+ # do_this_and_do_that_and_another_thing
39
+ #
40
+ # @see http://github.github.com/github-flavored-markdown/
41
+ # @see http://daringfireball.net/projects/markdown/syntax
42
+ #
43
+ class FlavoredMarkdown
44
+ # For maximum flavor, add one shake of seasoning to markdown text **before** cooking with a
45
+ # Markdown engine.
46
+ #
47
+ # @example Cooking with BlueCloth
48
+ #
49
+ # BlueCloth.new(Mango::FlavoredMarkdown.shake(text)).to_html
50
+ #
51
+ # @param [String] text
52
+ # @return [String] Seasoned text that is ready to cook!
53
+ #
54
+ def self.shake(text)
55
+ # Extract pre blocks
56
+ extractions = {}
57
+ text.gsub!(%r{<pre>.*?</pre>}m) do |match|
58
+ md5 = Digest::MD5.hexdigest(match)
59
+ extractions[md5] = match
60
+ "{gfm-extraction-#{md5}}"
61
+ end
62
+
63
+ # prevent foo_bar_baz from ending up with an italic word in the middle
64
+ text.gsub!(/(^(?! {4}|\t)\w+_\w+_\w[\w_]*)/) do |x|
65
+ x.gsub("_", '\_') if x.split('').sort.join[0..1] == "__"
66
+ end
67
+
68
+ # in very clear cases, let newlines become <br /> tags
69
+ text.gsub!(/^[\w\<][^\n]*\n+/) do |x|
70
+ x =~ /\n{2}/ ? x : (x.strip!; x << " \n")
71
+ end
72
+
73
+ # Insert pre block extractions
74
+ text.gsub!(/\{gfm-extraction-([0-9a-f]{32})\}/) do
75
+ "\n\n" + extractions[$1]
76
+ end
77
+
78
+ text
79
+ end
80
+
81
+ end
82
+ end
@@ -0,0 +1,22 @@
1
+ # encoding: UTF-8
2
+ module Mango
3
+ module Rack
4
+ class Debugger
5
+ def initialize(app, kernel = Kernel, ruby_version = RUBY_VERSION)
6
+ @app = app
7
+ kernel.require "ruby-debug"
8
+ ::Debugger.start
9
+ puts "=> Debugger enabled"
10
+ rescue LoadError
11
+ gem_name = (ruby_version >= "1.9" ? "ruby-debug19" : "ruby-debug")
12
+ puts "=> Debugger not enabled"
13
+ puts "=> The #{gem_name} library is required to run the server in debugging mode."
14
+ puts "=> With RubyGems, use 'gem install #{gem_name}' to install the library."
15
+ end
16
+
17
+ def call(env)
18
+ @app.call(env)
19
+ end
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,95 @@
1
+ # encoding: UTF-8
2
+ require "thor"
3
+
4
+ module Mango
5
+ class Runner < Thor
6
+ include Thor::Actions
7
+
8
+ add_runtime_options!
9
+
10
+ source_root File.join(File.dirname(__FILE__), "templates")
11
+
12
+ desc "create /path/to/your/app",
13
+ "Creates a new Mango application with a default directory structure and configuration at the path you specify."
14
+ def create(destination)
15
+ self.destination_root = destination
16
+ copy_file("config.ru", File.join(self.destination_root, "config.ru"))
17
+ copy_file("Gemfile", File.join(self.destination_root, "Gemfile"))
18
+ copy_file("README.md", File.join(self.destination_root, "README.md"))
19
+
20
+ build_content_path
21
+ build_themes_path
22
+ end
23
+
24
+ ###############################################################################################
25
+
26
+ protected
27
+
28
+ def build_content_path
29
+ content_root = File.join(self.destination_root, "content")
30
+ empty_directory(content_root)
31
+ copy_file("content/index.md", File.join(content_root, "index.md"))
32
+ end
33
+
34
+ def build_themes_path
35
+ themes_root = File.join(self.destination_root, "themes")
36
+ empty_directory(themes_root)
37
+
38
+ default_root = File.join(themes_root, "default")
39
+ empty_directory(default_root)
40
+
41
+ build_public_path default_root
42
+ build_styles_path default_root
43
+ build_views_path default_root
44
+ end
45
+
46
+ ###############################################################################################
47
+
48
+ protected
49
+
50
+ def build_public_path(destination)
51
+ public_root = File.join(destination, "public")
52
+ empty_directory(public_root)
53
+ create_file(File.join(public_root, "favicon.ico"))
54
+ copy_file("themes/default/public/robots.txt", File.join(public_root, "robots.txt"))
55
+
56
+ build_public_images_path public_root
57
+ build_public_javascripts_path public_root
58
+ build_public_styles_path public_root
59
+ end
60
+
61
+ def build_public_images_path(destination)
62
+ public_images_root = File.join(destination, "images")
63
+ empty_directory(public_images_root)
64
+ copy_file("themes/default/public/images/particles.gif", File.join(public_images_root, "particles.gif"))
65
+ end
66
+
67
+ def build_public_javascripts_path(destination)
68
+ public_javascripts_root = File.join(destination, "javascripts")
69
+ empty_directory(public_javascripts_root)
70
+ copy_file("themes/default/public/javascripts/fireworks.js", File.join(public_javascripts_root, "fireworks.js"))
71
+ copy_file("themes/default/public/javascripts/timer.js", File.join(public_javascripts_root, "timer.js"))
72
+ end
73
+
74
+ def build_public_styles_path(destination)
75
+ public_styles_root = File.join(destination, "styles")
76
+ empty_directory(public_styles_root)
77
+ copy_file("themes/default/public/styles/fireworks.css", File.join(public_styles_root, "fireworks.css"))
78
+ copy_file("themes/default/public/styles/reset.css", File.join(public_styles_root, "reset.css"))
79
+ end
80
+
81
+ def build_styles_path(destination)
82
+ styles_root = File.join(destination, "styles")
83
+ empty_directory(styles_root)
84
+ copy_file("themes/default/styles/screen.sass", File.join(styles_root, "screen.sass"))
85
+ end
86
+
87
+ def build_views_path(destination)
88
+ views_root = File.join(destination, "views")
89
+ empty_directory(views_root)
90
+ copy_file("themes/default/views/404.haml", File.join(views_root, "404.haml"))
91
+ copy_file("themes/default/views/layout.haml", File.join(views_root, "layout.haml"))
92
+ copy_file("themes/default/views/page.haml", File.join(views_root, "page.haml"))
93
+ end
94
+ end
95
+ end