suite 0.1.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/.gitignore +18 -0
- data/Gemfile +4 -0
- data/README.md +304 -0
- data/Rakefile +2 -0
- data/bin/suite +3 -0
- data/lib/suite/builder.rb +139 -0
- data/lib/suite/cli.rb +52 -0
- data/lib/suite/environment.rb +22 -0
- data/lib/suite/generators/project/application.js.erb +10 -0
- data/lib/suite/generators/project/application.scss.erb +5 -0
- data/lib/suite/generators/project/content.yml +16 -0
- data/lib/suite/generators/project/core.js.coffee +4 -0
- data/lib/suite/generators/project/gitignore +1 -0
- data/lib/suite/generators/project/homepage.html.haml +6 -0
- data/lib/suite/generators/project/info.html.haml +8 -0
- data/lib/suite/generators/project/suite.yml.erb +6 -0
- data/lib/suite/generators/project/template.html.haml.erb +44 -0
- data/lib/suite/generators/project/text.txt +1 -0
- data/lib/suite/generators/project.rb +69 -0
- data/lib/suite/helpers/image_view_helper.rb +14 -0
- data/lib/suite/helpers/javascript_view_helper.rb +23 -0
- data/lib/suite/helpers/stylesheet_view_helper.rb +13 -0
- data/lib/suite/helpers/view_helpers.rb +19 -0
- data/lib/suite/project/asset_registry.rb +62 -0
- data/lib/suite/project.rb +76 -0
- data/lib/suite/renderers/abstract.rb +21 -0
- data/lib/suite/renderers/exception.rb +17 -0
- data/lib/suite/renderers/haml.rb +12 -0
- data/lib/suite/renderers/html.rb +11 -0
- data/lib/suite/renderers/page.rb +59 -0
- data/lib/suite/renderers.rb +11 -0
- data/lib/suite/server/asset.rb +17 -0
- data/lib/suite/server/content.rb +18 -0
- data/lib/suite/server/error.rb +7 -0
- data/lib/suite/server/root_asset.rb +4 -0
- data/lib/suite/server.rb +16 -0
- data/lib/suite/version.rb +3 -0
- data/lib/suite.rb +33 -0
- data/suite.gemspec +30 -0
- metadata +196 -0
@@ -0,0 +1,69 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
require 'thor/group'
|
3
|
+
module Suite
|
4
|
+
module Generators
|
5
|
+
class Project < Thor::Group
|
6
|
+
include Thor::Actions
|
7
|
+
argument :name, type: :string
|
8
|
+
|
9
|
+
def create_config
|
10
|
+
say "I’m going to ask you some questions to create your config file", :cyan
|
11
|
+
say "You can change these values in your config/suite.yml file", :cyan
|
12
|
+
@compress_javascript = yes? "Compress JavaScript? [Yn]"
|
13
|
+
@shorten_javascript_variables = yes? "Shorten JavaScript Variables? [Yn]"
|
14
|
+
@compress_stylesheet = yes? "Compress CSS? [Yn]"
|
15
|
+
@using_cdn = yes? "Will you serve assets from a CDN?"
|
16
|
+
if @using_cdn
|
17
|
+
@asset_host = ask("CDN Host and path [e.g. http://ak43nam.cloudfront.net/new_site]").gsub(/\/$/,'')
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
def create_directory_structure
|
22
|
+
empty_directory
|
23
|
+
empty_directory "build"
|
24
|
+
empty_directory "config"
|
25
|
+
empty_directory "content"
|
26
|
+
empty_directory "content/layouts"
|
27
|
+
empty_directory "assets"
|
28
|
+
empty_directory "assets/images"
|
29
|
+
empty_directory "assets/javascripts"
|
30
|
+
empty_directory "assets/stylesheets"
|
31
|
+
end
|
32
|
+
|
33
|
+
def copy_files
|
34
|
+
template "application.js.erb", "#{name}/assets/javascripts/application.js"
|
35
|
+
template "core.js.coffee", "#{name}/assets/javascripts/core.js.coffee"
|
36
|
+
|
37
|
+
template "application.scss.erb", "#{name}/assets/stylesheets/#{name}.css.scss"
|
38
|
+
|
39
|
+
template "suite.yml.erb", "#{name}/config/suite.yml"
|
40
|
+
template "content.yml", "#{name}/config/content.yml"
|
41
|
+
|
42
|
+
template "template.html.haml.erb", "#{name}/content/layouts/application.html.haml"
|
43
|
+
template "homepage.html.haml", "#{name}/content/homepage.html.haml"
|
44
|
+
template "info.html.haml", "#{name}/content/info.html.haml"
|
45
|
+
end
|
46
|
+
|
47
|
+
def git
|
48
|
+
if yes? "Create git repo? [Yn]"
|
49
|
+
shell.mute do
|
50
|
+
inside name do
|
51
|
+
run 'git init'
|
52
|
+
end
|
53
|
+
template "gitignore", "#{name}/.gitignore"
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
private
|
59
|
+
|
60
|
+
def self.source_root
|
61
|
+
File.dirname(__FILE__) + "/project"
|
62
|
+
end
|
63
|
+
|
64
|
+
def empty_directory folder_name = nil
|
65
|
+
super "#{name}/#{folder_name}"
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
module Suite::Helpers
|
2
|
+
module ImageViewHelper
|
3
|
+
def image_tag src, attributes = {}
|
4
|
+
attrs = []
|
5
|
+
attributes.each_pair do |k,v|
|
6
|
+
final_value = v.is_a?(Array) ? v.join(" ") : v
|
7
|
+
final_value = ERB::Util.html_escape(final_value)
|
8
|
+
attrs << %(#{k}="#{final_value}")
|
9
|
+
end
|
10
|
+
|
11
|
+
"<img src=\"#{Suite.project.asset_path}/images/#{ERB::Util.html_escape src}\" #{attrs.sort * ' '} />"
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
module Suite::Helpers
|
2
|
+
module JavascriptViewHelper
|
3
|
+
def javascript_include_tag path
|
4
|
+
path = path + ".js" unless path =~ /\.js/
|
5
|
+
if Suite.env.development?
|
6
|
+
javascript_include_tags_for_asset(path)
|
7
|
+
else
|
8
|
+
javascript_script_tag "#{Suite.project.asset_path}/javascripts/#{Suite.project.asset_registry.add_asset :js, path}.js"
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
def javascript_include_tags_for_asset path
|
13
|
+
assets = Suite.project.asset path
|
14
|
+
assets.to_a.map do |asset|
|
15
|
+
javascript_script_tag clean_asset_path asset.pathname.to_s
|
16
|
+
end.join("\n")
|
17
|
+
end
|
18
|
+
|
19
|
+
def javascript_script_tag path
|
20
|
+
"<script type=\"text/javascript\" src=\"#{path}\"></script>"
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,13 @@
|
|
1
|
+
module Suite::Helpers
|
2
|
+
module StylesheetViewHelper
|
3
|
+
|
4
|
+
def stylesheet_link_tag path, media = :all
|
5
|
+
path = path + ".css" unless path =~ /\.css/
|
6
|
+
if Suite.env.build?
|
7
|
+
path = Suite.project.asset_registry.add_asset(:css, path) + ".css"
|
8
|
+
end
|
9
|
+
"<link rel=\"stylesheet\" href=\"#{Suite.project.asset_path}/stylesheets/#{path}\" media=\"#{media}\" />"
|
10
|
+
end
|
11
|
+
|
12
|
+
end
|
13
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
require 'suite/project/asset_registry'
|
2
|
+
require 'suite/helpers/image_view_helper'
|
3
|
+
require 'suite/helpers/javascript_view_helper'
|
4
|
+
require 'suite/helpers/stylesheet_view_helper'
|
5
|
+
|
6
|
+
module Suite
|
7
|
+
module Helpers
|
8
|
+
module ViewHelpers
|
9
|
+
include ImageViewHelper
|
10
|
+
include JavascriptViewHelper
|
11
|
+
include StylesheetViewHelper
|
12
|
+
|
13
|
+
def clean_asset_path path
|
14
|
+
path.sub(/\.coffee|\.scss|\.sass/,'').sub(Suite.project.path,'')
|
15
|
+
end
|
16
|
+
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,62 @@
|
|
1
|
+
require 'digest/md5'
|
2
|
+
module Suite
|
3
|
+
class AssetRegistry
|
4
|
+
|
5
|
+
attr_accessor :assets
|
6
|
+
|
7
|
+
def initialize
|
8
|
+
@assets = { js: {}, css: {} }
|
9
|
+
end
|
10
|
+
|
11
|
+
def add_asset type, path
|
12
|
+
@assets[type][path] = Suite::Asset.new(path, type) unless @assets[type][path]
|
13
|
+
@assets[type][path].identifier
|
14
|
+
end
|
15
|
+
|
16
|
+
def js
|
17
|
+
@assets[:js]
|
18
|
+
end
|
19
|
+
|
20
|
+
def css
|
21
|
+
@assets[:css]
|
22
|
+
end
|
23
|
+
|
24
|
+
end
|
25
|
+
class Asset
|
26
|
+
attr_accessor :path, :type
|
27
|
+
def initialize path, type
|
28
|
+
@path, @type = path, type
|
29
|
+
end
|
30
|
+
|
31
|
+
def identifier
|
32
|
+
Digest::MD5.hexdigest to_s
|
33
|
+
end
|
34
|
+
|
35
|
+
def build_file_name
|
36
|
+
"#{identifier}.#{type.downcase}"
|
37
|
+
end
|
38
|
+
|
39
|
+
def to_s
|
40
|
+
@_memoized_to_s ||= compress Suite.project.asset(@path).to_s
|
41
|
+
end
|
42
|
+
|
43
|
+
def compress content
|
44
|
+
case type
|
45
|
+
when :js
|
46
|
+
if Suite.project.config["compress_javascript"]
|
47
|
+
YUI::JavaScriptCompressor.new(:munge => Suite.project.config["shorten_javascript_variables"]).compress content
|
48
|
+
else
|
49
|
+
content
|
50
|
+
end
|
51
|
+
when :css
|
52
|
+
if Suite.project.config["compress_css"]
|
53
|
+
YUI::CssCompressor.new.compress content
|
54
|
+
else
|
55
|
+
content
|
56
|
+
end
|
57
|
+
else
|
58
|
+
raise "Could not find YUI compressor for '#{type}'"
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
@@ -0,0 +1,76 @@
|
|
1
|
+
require 'suite/renderers'
|
2
|
+
require 'sprockets'
|
3
|
+
module Suite
|
4
|
+
class Project
|
5
|
+
attr_accessor :path, :config, :content, :view
|
6
|
+
def initialize path, config, content, view
|
7
|
+
@path, @config, @content, @view = path, config, content, view
|
8
|
+
end
|
9
|
+
|
10
|
+
def config
|
11
|
+
@config || {}
|
12
|
+
end
|
13
|
+
|
14
|
+
# Retrieves the content hash for the current view
|
15
|
+
def content
|
16
|
+
@content[view.to_s] || raise("No view '#{view}' defined")
|
17
|
+
end
|
18
|
+
|
19
|
+
def pages
|
20
|
+
content["pages"]
|
21
|
+
end
|
22
|
+
|
23
|
+
def include? slugs
|
24
|
+
return !!content_at_slugs(slugs)
|
25
|
+
end
|
26
|
+
|
27
|
+
def page_at_slugs slugs
|
28
|
+
content_level = pages
|
29
|
+
slugs.each do |slug|
|
30
|
+
return false unless content_level = content_level[slug.to_s]
|
31
|
+
end
|
32
|
+
return {
|
33
|
+
layout: content_level["layout"] ? content_level["layout"] : content["layout"],
|
34
|
+
content: content_level["content"]
|
35
|
+
}
|
36
|
+
end
|
37
|
+
|
38
|
+
def file_types
|
39
|
+
config["file_types"] || [:html]
|
40
|
+
end
|
41
|
+
|
42
|
+
def asset path
|
43
|
+
sprocket_environment[path.sub(/javascripts\/|stylesheets\/|images\//,'')]
|
44
|
+
end
|
45
|
+
|
46
|
+
def source_asset_path
|
47
|
+
path + "/assets"
|
48
|
+
end
|
49
|
+
|
50
|
+
def asset_path
|
51
|
+
Suite.env.build? && config["asset_host"] ? config["asset_host"].gsub(/\/$/,'') : "/assets"
|
52
|
+
end
|
53
|
+
|
54
|
+
def asset_registry
|
55
|
+
@_memoized_asset_registry ||= Suite::AssetRegistry.new
|
56
|
+
end
|
57
|
+
|
58
|
+
def sprocket_environment
|
59
|
+
@_memorized_sprocket_environment ||= begin
|
60
|
+
environment = Sprockets::Environment.new
|
61
|
+
environment.append_path source_asset_path + '/images'
|
62
|
+
environment.append_path source_asset_path + '/javascripts'
|
63
|
+
environment.append_path source_asset_path + '/stylesheets'
|
64
|
+
environment
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
# TODO: Puts a renderers config in the yaml to add new renderers
|
69
|
+
def renderers
|
70
|
+
@_memoized_render_types ||= begin
|
71
|
+
Suite::Renderers.default_renderers
|
72
|
+
end
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
@@ -0,0 +1,21 @@
|
|
1
|
+
require 'suite/helpers/view_helpers'
|
2
|
+
|
3
|
+
module Suite::Renderers
|
4
|
+
class Abstract
|
5
|
+
include Suite::Helpers::ViewHelpers
|
6
|
+
|
7
|
+
def self.render_file path, &block
|
8
|
+
new(IO.read path).render &block
|
9
|
+
end
|
10
|
+
|
11
|
+
def self.render content
|
12
|
+
new(content).render
|
13
|
+
end
|
14
|
+
|
15
|
+
attr_accessor :content
|
16
|
+
def initialize content
|
17
|
+
@content = content
|
18
|
+
end
|
19
|
+
|
20
|
+
end
|
21
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
module Suite
|
2
|
+
module Renderers
|
3
|
+
class Exception
|
4
|
+
attr_accessor :message
|
5
|
+
def initialize message
|
6
|
+
@message = message
|
7
|
+
if Suite.env.build?
|
8
|
+
raise message.gsub(/<([^>]*)>/,'"')
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
def to_s
|
13
|
+
"<div style='position:fixed; top:0; left:0; width: 100%; font-family: sans-serif; text-align:center; font-size:24px; padding:25px; background-color:#FFF3C2;'>#{message}</div>"
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,59 @@
|
|
1
|
+
require 'suite/renderers/haml'
|
2
|
+
require 'suite/renderers/html'
|
3
|
+
require 'suite/renderers/exception'
|
4
|
+
|
5
|
+
module Suite::Renderers
|
6
|
+
class Page
|
7
|
+
attr_accessor :layout, :partials, :contents
|
8
|
+
|
9
|
+
def initialize layout, partials
|
10
|
+
@layout, @partials, @contents = layout, partials, {}
|
11
|
+
end
|
12
|
+
|
13
|
+
def render
|
14
|
+
render_layout(partials.map do |partial|
|
15
|
+
render_partial partial
|
16
|
+
end.join("\n"))
|
17
|
+
end
|
18
|
+
|
19
|
+
def render_layout body
|
20
|
+
return body unless layout
|
21
|
+
Suite::Renderers::HAML.render_file(layout_path) do |location|
|
22
|
+
if location
|
23
|
+
@contents[location]
|
24
|
+
else
|
25
|
+
body
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
def render_partial partial
|
31
|
+
root = Suite.project.path + "/content/" + partial
|
32
|
+
output = nil
|
33
|
+
Suite.project.file_types.each do |file_type|
|
34
|
+
Suite.project.renderers.each do |extension, renderer|
|
35
|
+
path = root + "." + file_type.to_s + "." + extension.to_s
|
36
|
+
if File.exists?(path)
|
37
|
+
output = renderer.render_file(path)
|
38
|
+
break
|
39
|
+
end
|
40
|
+
end
|
41
|
+
break if output
|
42
|
+
path = root + ".html"
|
43
|
+
if File.exists?(path)
|
44
|
+
output = Suite::Renderers::HTML.render_file(path, @contents)
|
45
|
+
break
|
46
|
+
end
|
47
|
+
end
|
48
|
+
output ? output : missing_partial(partial)
|
49
|
+
end
|
50
|
+
|
51
|
+
def layout_path
|
52
|
+
Suite.project.path + "/content/" + layout + ".html.haml"
|
53
|
+
end
|
54
|
+
|
55
|
+
def missing_partial partial
|
56
|
+
Suite::Renderers::Exception.new "Could not find partial <strong>#{partial}</strong>"
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
require 'suite/server/error'
|
2
|
+
require 'mime/types'
|
3
|
+
|
4
|
+
module Suite
|
5
|
+
class AssetServer < Goliath::API
|
6
|
+
include Suite::ServerError
|
7
|
+
def response(env)
|
8
|
+
asset = Suite.project.asset env.params[:asset].join("/")
|
9
|
+
return not_found unless asset
|
10
|
+
[
|
11
|
+
200,
|
12
|
+
{'content-type'=> MIME::Types.type_for(env.params[:asset].last).first.content_type },
|
13
|
+
asset.body
|
14
|
+
]
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
require 'suite/server/error'
|
2
|
+
require 'suite/renderers/page'
|
3
|
+
|
4
|
+
module Suite
|
5
|
+
class ContentServer < Goliath::API
|
6
|
+
include Suite::ServerError
|
7
|
+
def response env
|
8
|
+
return not_found unless page = Suite.project.page_at_slugs(slugs)
|
9
|
+
renderer = Suite::Renderers::Page.new page[:layout], page[:content]
|
10
|
+
[200,{},renderer.render]
|
11
|
+
end
|
12
|
+
|
13
|
+
# Returns the array of slugs, or index if no slug
|
14
|
+
def slugs
|
15
|
+
self.env.params[:content].map{ |slug| slug == "" ? "index" : slug }
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
data/lib/suite/server.rb
ADDED
@@ -0,0 +1,16 @@
|
|
1
|
+
require 'goliath/api'
|
2
|
+
require 'goliath/runner'
|
3
|
+
require 'suite/server/asset'
|
4
|
+
require 'suite/server/root_asset'
|
5
|
+
require 'suite/server/content'
|
6
|
+
|
7
|
+
module Suite
|
8
|
+
class Server < Goliath::API
|
9
|
+
map "/assets/*asset", Suite::AssetServer
|
10
|
+
map "/*content", Suite::ContentServer
|
11
|
+
|
12
|
+
%w[favicon.ico].each do |resource|
|
13
|
+
map "/#{resource}", Suite::RootAssetServer
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
data/lib/suite.rb
ADDED
@@ -0,0 +1,33 @@
|
|
1
|
+
require 'suite/project'
|
2
|
+
require 'suite/environment'
|
3
|
+
require "suite/version"
|
4
|
+
require "suite/cli"
|
5
|
+
require 'yaml'
|
6
|
+
|
7
|
+
module Suite
|
8
|
+
class << self
|
9
|
+
def project= project
|
10
|
+
@@project = project
|
11
|
+
end
|
12
|
+
|
13
|
+
def project
|
14
|
+
@@project
|
15
|
+
end
|
16
|
+
|
17
|
+
def env= env
|
18
|
+
@@env = env
|
19
|
+
end
|
20
|
+
|
21
|
+
def env
|
22
|
+
@@env ||= Suite::Environment.new(ENV["SUITE_ENV"] || :development)
|
23
|
+
end
|
24
|
+
|
25
|
+
def use_project_at_path path, view = :desktop
|
26
|
+
self.project = Suite::Project.new \
|
27
|
+
path,
|
28
|
+
YAML.load(File.open(path + "/config/suite.yml")),
|
29
|
+
YAML.load(File.open(path + "/config/content.yml")),
|
30
|
+
view
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
data/suite.gemspec
ADDED
@@ -0,0 +1,30 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
require File.expand_path('../lib/suite/version', __FILE__)
|
3
|
+
|
4
|
+
Gem::Specification.new do |gem|
|
5
|
+
gem.authors = ["Mal Curtis"]
|
6
|
+
gem.email = ["mal@mal.co.nz"]
|
7
|
+
gem.description = %q{All the stuff that make front end web development fun, in one simple toolkit}
|
8
|
+
gem.summary = gem.description
|
9
|
+
gem.homepage = ""
|
10
|
+
|
11
|
+
gem.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
|
12
|
+
gem.files = `git ls-files`.split("\n")
|
13
|
+
gem.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|
14
|
+
gem.name = "suite"
|
15
|
+
gem.require_paths = ["lib"]
|
16
|
+
gem.version = Suite::VERSION
|
17
|
+
|
18
|
+
|
19
|
+
gem.add_development_dependency "rspec", "~> 2.6"
|
20
|
+
gem.add_dependency "thor"
|
21
|
+
gem.add_dependency "goliath"
|
22
|
+
gem.add_dependency "mime-types"
|
23
|
+
gem.add_dependency "haml"
|
24
|
+
gem.add_dependency "sprockets"
|
25
|
+
gem.add_dependency "sprockets-sass"
|
26
|
+
gem.add_dependency "coffee-script"
|
27
|
+
gem.add_dependency "compass"
|
28
|
+
gem.add_dependency "yui-compressor"
|
29
|
+
|
30
|
+
end
|