tipsy 0.0.1 → 0.0.2
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/Gemfile +9 -0
- data/README.md +2 -2
- data/Rakefile +10 -0
- data/bin/tipsy +16 -5
- data/lib/tipsy.rb +26 -14
- data/lib/tipsy/application.rb +14 -16
- data/lib/tipsy/builder.rb +17 -4
- data/lib/tipsy/builders/base.rb +64 -0
- data/lib/tipsy/builders/export.rb +16 -0
- data/lib/tipsy/builders/project.rb +40 -0
- data/lib/tipsy/builders/remote.rb +14 -0
- data/lib/tipsy/compressors/css.rb +11 -0
- data/lib/tipsy/compressors/javascript.rb +25 -0
- data/lib/tipsy/helpers.rb +24 -1
- data/lib/tipsy/helpers/asset_paths.rb +19 -0
- data/lib/tipsy/helpers/asset_tags.rb +32 -0
- data/lib/tipsy/helpers/capture.rb +33 -0
- data/lib/tipsy/helpers/sass.rb +40 -0
- data/lib/tipsy/helpers/tag.rb +12 -0
- data/lib/tipsy/logger.rb +54 -3
- data/lib/tipsy/project/Gemfile +8 -0
- data/lib/tipsy/project/config.erb +5 -2
- data/lib/tipsy/sass/template.rb +137 -0
- data/lib/tipsy/server.rb +50 -7
- data/lib/tipsy/version.rb +1 -1
- data/lib/tipsy/view.rb +24 -10
- data/test/fixtures/about.html +1 -0
- data/test/fixtures/contact.html +1 -0
- data/test/fixtures/index.html +1 -0
- data/test/functional/page_test.rb +33 -0
- data/test/root/{assets → development/assets}/javascripts/test.js +0 -0
- data/test/root/{assets → development/assets}/stylesheets/screen.css.scss +0 -0
- data/test/root/{config.rb → development/config.rb} +0 -0
- data/test/root/{views → development/views}/_layout.html.erb +0 -0
- data/test/root/{views → development/views}/index.html.erb +0 -0
- data/test/root/test/assets/javascripts/test.js +0 -0
- data/test/root/test/assets/stylesheets/screen.css.scss +3 -0
- data/test/root/test/config.rb +6 -0
- data/test/root/test/views/_layout.html.erb +1 -0
- data/test/root/test/views/about/index.html +1 -0
- data/test/root/test/views/contact.html +1 -0
- data/test/root/test/views/index.html.erb +1 -0
- data/test/test_helper.rb +33 -0
- data/test/unit/helpers/asset_paths_test.rb +14 -0
- data/test/unit/helpers_test.rb +22 -0
- data/test/unit/server_test.rb +1 -0
- data/tipsy.gemspec +5 -4
- metadata +83 -35
- data/config.ru +0 -26
- data/lib/tipsy/generator.rb +0 -53
data/Gemfile
CHANGED
@@ -3,3 +3,12 @@ gemspec
|
|
3
3
|
|
4
4
|
gem 'facades', :path => '/_Work/gems/facades'
|
5
5
|
gem 'thin'
|
6
|
+
|
7
|
+
group :test do
|
8
|
+
gem 'jnunemaker-matchy', '~> 0.4.0', :require => 'matchy'
|
9
|
+
gem 'shoulda', '~> 2.11'
|
10
|
+
gem 'mocha', '~> 0.9.12'
|
11
|
+
gem 'rack-test'
|
12
|
+
gem 'turn'
|
13
|
+
gem 'minitest'
|
14
|
+
end
|
data/README.md
CHANGED
@@ -1,10 +1,10 @@
|
|
1
|
-
|
1
|
+
# Tipsy
|
2
2
|
|
3
3
|
Tipsy is a small Rack-based server inspired by gems like StaticMatic and Serve. Its purpose is to aid development of static sites by providing
|
4
4
|
Rails-esque style templating and helpers. Various template types are supported via the Tilt gem, and assets are served via Sprockets, essentially giving you
|
5
5
|
a miniture Rails "view-only" environment.
|
6
6
|
|
7
|
-
|
7
|
+
### Notes
|
8
8
|
|
9
9
|
Tipsy was developed for personal/internal use but feature/pull requests are gladly accepted. It is not designed to function in any kind of production
|
10
10
|
environment. When ready to upload files to a production environment, build the project and upload the result.
|
data/Rakefile
CHANGED
data/bin/tipsy
CHANGED
@@ -1,10 +1,21 @@
|
|
1
1
|
#!/usr/bin/env ruby
|
2
2
|
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
3
|
+
libdir = File.dirname(__FILE__) + '/../lib'
|
4
|
+
if File.file?(libdir + '/tipsy/version.rb')
|
5
|
+
$LOAD_PATH.unshift(libdir)
|
6
|
+
end
|
7
|
+
|
8
|
+
begin
|
9
|
+
require 'tipsy'
|
10
|
+
rescue LoadError
|
11
|
+
require 'rubygems'
|
12
|
+
retry
|
13
|
+
end
|
14
|
+
|
15
|
+
if File.exists?(File.join(File.expand_path('.'), 'Gemfile'))
|
16
|
+
require 'bundler/setup'
|
17
|
+
Bundler.require(:default)
|
18
|
+
end
|
7
19
|
|
8
|
-
require 'tipsy'
|
9
20
|
Tipsy.root = File.expand_path('.')
|
10
21
|
Tipsy.run_command(ARGV, STDIN)
|
data/lib/tipsy.rb
CHANGED
@@ -8,17 +8,29 @@ module Tipsy
|
|
8
8
|
autoload :Application, 'tipsy/application'
|
9
9
|
autoload :Server, 'tipsy/server'
|
10
10
|
autoload :Responder, 'tipsy/handler'
|
11
|
+
autoload :Helpers, 'tipsy/helpers'
|
12
|
+
autoload :Builder, 'tipsy/builder'
|
13
|
+
autoload :Logger, 'tipsy/logger'
|
11
14
|
autoload :View, 'tipsy/view'
|
12
|
-
autoload :Helpers, 'tipsy/helpers'
|
13
15
|
|
14
|
-
|
15
|
-
|
16
|
-
|
16
|
+
module Compressors
|
17
|
+
autoload :CssCompressor, 'tipsy/compressors/css'
|
18
|
+
autoload :JavascriptCompressor, 'tipsy/compressors/javascript'
|
19
|
+
end
|
20
|
+
|
21
|
+
module Sass
|
22
|
+
autoload :Template, 'tipsy/sass/template'
|
23
|
+
end
|
24
|
+
|
17
25
|
mattr_accessor :root
|
18
26
|
mattr_accessor :logger
|
19
27
|
mattr_accessor :env
|
20
28
|
mattr_accessor :sprockets
|
21
29
|
mattr_accessor :compass
|
30
|
+
|
31
|
+
def self.logger
|
32
|
+
@logger ||= Tipsy::Logger.new($stdout)
|
33
|
+
end
|
22
34
|
|
23
35
|
def self.run_command(args, stdin)
|
24
36
|
args = [args].flatten
|
@@ -31,20 +43,20 @@ module Tipsy
|
|
31
43
|
end
|
32
44
|
|
33
45
|
args.shift
|
34
|
-
|
35
|
-
options.port = 4000
|
36
|
-
options.host = '0.0.0.0'
|
37
|
-
options.assets = []
|
38
|
-
options.build_path = File.join(Tipsy.root, 'build')
|
39
|
-
options.public_path = File.join(Tipsy.root, 'public')
|
40
|
-
options.asset_path = File.join(options.public_path, 'assets')
|
41
|
-
|
42
|
-
parse_options!
|
46
|
+
parse_options!
|
43
47
|
Tipsy::Application.send(:"#{to_run}", *args)
|
48
|
+
|
44
49
|
end
|
45
50
|
|
46
51
|
def self.options
|
47
|
-
@@options ||= OpenStruct.new
|
52
|
+
@@options ||= OpenStruct.new({
|
53
|
+
:port => 4000,
|
54
|
+
:host => '0.0.0.0',
|
55
|
+
:assets => OpenStruct.new({ :paths => [], :precompile => [] }),
|
56
|
+
:build_path => File.join(Tipsy.root, 'build'),
|
57
|
+
:public_path => File.join(Tipsy.root, 'public'),
|
58
|
+
:asset_path => File.join(Tipsy.root, 'public', 'assets')
|
59
|
+
})
|
48
60
|
end
|
49
61
|
|
50
62
|
private
|
data/lib/tipsy/application.rb
CHANGED
@@ -1,6 +1,9 @@
|
|
1
1
|
require 'rack'
|
2
|
-
require 'tipsy/server'
|
3
2
|
|
3
|
+
##
|
4
|
+
# Base class for all applications. Handles configuration of options,
|
5
|
+
# and processing of command line arguments.
|
6
|
+
#
|
4
7
|
module Tipsy
|
5
8
|
class Application
|
6
9
|
|
@@ -9,11 +12,15 @@ module Tipsy
|
|
9
12
|
|
10
13
|
def self.create(name = nil)
|
11
14
|
raise "Missing project name for 'tipsy new'" unless name
|
12
|
-
Tipsy::
|
15
|
+
Tipsy::Builder.build!(:project, name)
|
13
16
|
end
|
14
17
|
|
15
18
|
def self.build
|
16
|
-
Tipsy::Builder.
|
19
|
+
Tipsy::Builder.build!(:export)
|
20
|
+
end
|
21
|
+
|
22
|
+
def self.deploy
|
23
|
+
Tipsy::Builder.build!(:remote)
|
17
24
|
end
|
18
25
|
|
19
26
|
def self.initialize!
|
@@ -31,19 +38,10 @@ module Tipsy
|
|
31
38
|
end
|
32
39
|
|
33
40
|
def initialize
|
41
|
+
require 'tipsy/helpers/sass'
|
42
|
+
@app = Tipsy::Server.init!
|
34
43
|
|
35
|
-
|
36
|
-
use Rack::CommonLogger
|
37
|
-
use Rack::ShowStatus
|
38
|
-
use Rack::ShowExceptions
|
39
|
-
use Tipsy::StaticFile, :root => Tipsy.options.public_path, :urls => %w[/]
|
40
|
-
run Rack::Cascade.new([
|
41
|
-
Rack::URLMap.new({ "/#{File.basename(Tipsy.options.asset_path)}" => Tipsy::AssetHandler.new }),
|
42
|
-
Tipsy::Server.new
|
43
|
-
])
|
44
|
-
}
|
45
|
-
|
46
|
-
puts "Tipsy #{Tipsy::VERSION} running on #{config.address}:#{config.port}"
|
44
|
+
Tipsy.logger.info("Tipsy #{Tipsy::VERSION} running on #{config.address}:#{config.port}")
|
47
45
|
|
48
46
|
begin run_thin
|
49
47
|
rescue LoadError
|
@@ -79,7 +77,7 @@ module Tipsy
|
|
79
77
|
def run_webrick
|
80
78
|
handler = Rack::Handler.get('webrick')
|
81
79
|
handler.run app, server_opts do |server|
|
82
|
-
puts "Running Tipsy with Webrick. To use Mongrel or Thin, add them to your Gemfile"
|
80
|
+
puts "Running Tipsy with Webrick. To use Mongrel or Thin (recommended), add them to your Gemfile"
|
83
81
|
trap("INT"){ server.shutdown }
|
84
82
|
end
|
85
83
|
end
|
data/lib/tipsy/builder.rb
CHANGED
@@ -1,12 +1,25 @@
|
|
1
1
|
require 'active_support/inflector'
|
2
2
|
|
3
|
+
##
|
4
|
+
# Handles building source files into a final project, for
|
5
|
+
# either deployment or output to a directory
|
6
|
+
#
|
3
7
|
module Tipsy
|
4
|
-
|
8
|
+
module Builder
|
5
9
|
|
6
|
-
|
10
|
+
autoload :Base, 'tipsy/builders/base'
|
11
|
+
autoload :ProjectBuilder, 'tipsy/builders/project'
|
12
|
+
autoload :ExportBuilder, 'tipsy/builders/local'
|
13
|
+
autoload :RemoteBuilder, 'tipsy/builders/remote'
|
7
14
|
|
8
|
-
def
|
9
|
-
|
15
|
+
def self.build!(type = :project, *args)
|
16
|
+
handler = case type
|
17
|
+
when :project then ProjectBuilder.new(*args)
|
18
|
+
when :export then ExportBuilder.new(*args)
|
19
|
+
when :remote then RemoteBuilder.new(*args)
|
20
|
+
else raise 'No builder specified'
|
21
|
+
end
|
22
|
+
handler.build!
|
10
23
|
end
|
11
24
|
|
12
25
|
end
|
@@ -0,0 +1,64 @@
|
|
1
|
+
module Tipsy
|
2
|
+
module Builder
|
3
|
+
class Base
|
4
|
+
attr_reader :source_path, :dest_path
|
5
|
+
|
6
|
+
def excludes
|
7
|
+
@excludes ||= ['.git', '.gitignore', '.sass-cache', 'config.erb', '*.rb', '.', '..']
|
8
|
+
end
|
9
|
+
|
10
|
+
def build!
|
11
|
+
process_location(source_path, dest_path)
|
12
|
+
end
|
13
|
+
|
14
|
+
protected
|
15
|
+
|
16
|
+
def excluded?(file)
|
17
|
+
return true if excludes.include?(file)
|
18
|
+
excludes.detect{ |exc| File.basename(exc).to_s.match(exc) }.nil?
|
19
|
+
end
|
20
|
+
|
21
|
+
def log_action(action, name)
|
22
|
+
name = name.gsub(dest_path, '').sub(/^\//, '')
|
23
|
+
Tipsy.logger.log_action(action, name)
|
24
|
+
end
|
25
|
+
|
26
|
+
##
|
27
|
+
# By default make_file copies from one location to another
|
28
|
+
# Overridden in non-local scenarios
|
29
|
+
#
|
30
|
+
def make_file(source, destination)
|
31
|
+
log_action("create", destination)
|
32
|
+
FileUtils.cp(source, destination)
|
33
|
+
end
|
34
|
+
|
35
|
+
##
|
36
|
+
# By default make_folder makes a matching folder in destination from source
|
37
|
+
# Overridden in non-local scenarios
|
38
|
+
#
|
39
|
+
def make_folder(dirname)
|
40
|
+
log_action("create", dirname)
|
41
|
+
FileUtils.mkdir(dirname)
|
42
|
+
end
|
43
|
+
|
44
|
+
##
|
45
|
+
# Iterate through a file tree and process each file and folder.
|
46
|
+
#
|
47
|
+
def process_location(src, dest)
|
48
|
+
Dir.foreach(src) do |file|
|
49
|
+
next if excluded?(file)
|
50
|
+
source = File.join(src, file)
|
51
|
+
destination = File.join(dest, file)
|
52
|
+
|
53
|
+
if File.directory?(source)
|
54
|
+
make_folder(destination)
|
55
|
+
process_location(source, destination)
|
56
|
+
else
|
57
|
+
make_file(source, destination)
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
module Tipsy
|
2
|
+
module Builder
|
3
|
+
class ExportBuilder < Base
|
4
|
+
|
5
|
+
def initialize
|
6
|
+
@source_path = Tipsy.root
|
7
|
+
@dest_path = Tipsy.options.build_path
|
8
|
+
end
|
9
|
+
|
10
|
+
def build!
|
11
|
+
FileUtils.mkdir(dest_path) unless File.exists?(dest_path) && File.directory?(dest_path)
|
12
|
+
end
|
13
|
+
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
@@ -0,0 +1,40 @@
|
|
1
|
+
require 'fileutils'
|
2
|
+
require 'erb'
|
3
|
+
|
4
|
+
module Tipsy
|
5
|
+
module Builder
|
6
|
+
class ProjectBuilder < Base
|
7
|
+
attr_reader :project
|
8
|
+
|
9
|
+
def initialize(name)
|
10
|
+
@project = name.camelize
|
11
|
+
@dest_path = File.join(Tipsy.root, name.underscore)
|
12
|
+
@source_path = File.expand_path("../../project", __FILE__)
|
13
|
+
end
|
14
|
+
|
15
|
+
def build!
|
16
|
+
|
17
|
+
FileUtils.mkdir(dest_path) unless File.exists?(dest_path)
|
18
|
+
super
|
19
|
+
cvars = Conf.new
|
20
|
+
cvars.root = dest_path
|
21
|
+
cvars.classname = @project
|
22
|
+
template = File.read(File.join(source_path, 'config.erb'))
|
23
|
+
config = ERB.new(template).result(cvars.get_binding)
|
24
|
+
|
25
|
+
File.open(File.join(dest_path, 'config.rb'), 'w'){ |io| io.write(config) }
|
26
|
+
log_action('create', File.join(dest_path, 'config.rb'))
|
27
|
+
|
28
|
+
Tipsy.logger.info("\n Project #{project} created in #{dest_path}.")
|
29
|
+
Tipsy.logger.info(" Run 'tipsy' from the root folder to start the server.\n\n")
|
30
|
+
|
31
|
+
end
|
32
|
+
|
33
|
+
class Conf
|
34
|
+
attr_accessor :classname, :root
|
35
|
+
def get_binding; binding; end
|
36
|
+
end
|
37
|
+
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
##
|
2
|
+
# Interface to Google's Online Closure Compiler.
|
3
|
+
# Uglifier is recommended (gem install uglifier) however to support environments where Node.js
|
4
|
+
# is unavailable this can be used as a fallback.
|
5
|
+
#
|
6
|
+
require 'net/http'
|
7
|
+
require 'uri'
|
8
|
+
|
9
|
+
module Tipsy
|
10
|
+
module Compressors
|
11
|
+
# http://closure-compiler.appspot.com/compile
|
12
|
+
class JavascriptCompressor
|
13
|
+
def compress(js)
|
14
|
+
return js if js.to_s.blank?
|
15
|
+
post_data = {
|
16
|
+
'compilation_level' => 'SIMPLE_OPTIMIZATIONS',
|
17
|
+
'js_code' => js.to_s,
|
18
|
+
'output_format' => 'text'
|
19
|
+
}
|
20
|
+
request = Net::HTTP.post_form(URI.parse('http://closure-compiler.appspot.com/compile'), post_data)
|
21
|
+
request.body.to_s
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
data/lib/tipsy/helpers.rb
CHANGED
@@ -1,9 +1,32 @@
|
|
1
|
+
require 'active_support/core_ext/array'
|
2
|
+
|
3
|
+
require 'tipsy/helpers/asset_paths'
|
1
4
|
require 'tipsy/helpers/capture'
|
2
5
|
require 'tipsy/helpers/tag'
|
6
|
+
require 'tipsy/helpers/asset_tags'
|
7
|
+
require 'tipsy/helpers/sass'
|
3
8
|
|
4
9
|
module Tipsy
|
5
10
|
module Helpers
|
11
|
+
extend ActiveSupport::Concern
|
6
12
|
include Capture
|
7
|
-
include Tag
|
13
|
+
include Tag
|
14
|
+
include AssetPaths
|
15
|
+
include AssetTags
|
16
|
+
|
17
|
+
module InstanceMethods
|
18
|
+
private
|
19
|
+
|
20
|
+
def __initialize_helpers
|
21
|
+
module_names = []
|
22
|
+
includes = Dir.glob(File.expand_path(Tipsy.root) << "/helpers/*.rb").inject([]) do |arr, helper|
|
23
|
+
module_names << File.basename(helper, '.rb').classify
|
24
|
+
arr.concat File.open(helper).readlines
|
25
|
+
end
|
26
|
+
module_names.each{ |mod| includes.concat(["\n include #{mod}"]) }
|
27
|
+
self.class_eval(includes.join("\n"))
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
8
31
|
end
|
9
32
|
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
require 'pathname'
|
2
|
+
|
3
|
+
module Tipsy
|
4
|
+
module Helpers
|
5
|
+
module AssetPaths
|
6
|
+
|
7
|
+
def asset_path(path)
|
8
|
+
return path if path.match(/^https?:/) || Pathname.new(path).absolute?
|
9
|
+
"/" << File.join('assets', path)
|
10
|
+
end
|
11
|
+
|
12
|
+
def path_with_ext(path, ext)
|
13
|
+
return path if path.match(/^https?:/) || path.ends_with?(".#{ext}")
|
14
|
+
[path, ext].join('.')
|
15
|
+
end
|
16
|
+
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|