fuse 0.1.3 → 0.1.4

Sign up to get free protection for your applications and to get access to all the features.
data/lib/fuse.rb CHANGED
@@ -3,12 +3,36 @@ require 'thin'
3
3
 
4
4
  module Fuse
5
5
 
6
- VERSION = '0.1.3'
6
+ VERSION = '0.1.4'
7
+
8
+ LOG_COLOURS = {
9
+ info: 6, # cyan
10
+ success: 2, # green
11
+ error: 1, # red
12
+ notice: 3 # yellow
13
+ }
7
14
 
8
15
  def self.root
9
16
  @root ||= File.expand_path File.dirname(__FILE__)
10
17
  end
11
18
 
19
+ def self.log_file=(file)
20
+ @log_file = file
21
+ end
22
+
23
+ def self.log_file
24
+ @log_file ||= $stderr
25
+ end
26
+
27
+ def self.log(message, type = nil)
28
+ m = "\x1b["
29
+ m << (30 + (LOG_COLOURS[type] || LOG_COLOURS[:info])).to_s
30
+ m << 'm'
31
+ m << message
32
+ m << "\x1b[0m"
33
+ log_file.puts m
34
+ end
35
+
12
36
  end
13
37
 
14
38
  $:.unshift Fuse.root unless $:.include?(Fuse.root)
data/lib/fuse/document.rb CHANGED
@@ -37,6 +37,7 @@ class Fuse::Document
37
37
  collection = assets.of_type(klass).sort!
38
38
  next unless collection.length > 0
39
39
  if @options[:embed_assets]
40
+ #todo recreate stylesheet media attributes
40
41
  tag = Nokogiri::XML::Node.new(klass::EMBED_WITH, document)
41
42
  raw = collection.map do |asset|
42
43
  tag['type'] = asset.type
@@ -125,7 +126,7 @@ class Fuse::Document
125
126
  raise Fuse::Exception::SourceUnknown::NotFound.new(option_value) unless File.exists?(option_value)
126
127
  return [option_value] unless File.directory? option_value
127
128
  end
128
- Dir[File.join(option_value || root, "**/*.{#{extensions.join(',')}}")]
129
+ Dir[File.join(option_value || root, "**/*.{#{extensions.join(',')}}")].select{ |f| File.size? f }
129
130
  end
130
131
 
131
132
  def expect_one(list, option, missing_exception)
@@ -30,7 +30,7 @@ class Fuse::Document::Asset
30
30
  end
31
31
 
32
32
  def relative_path
33
- @relative_path ||= path.sub(%r`^/`, '')
33
+ @relative_path ||= path.sub(%r`^[\\/]`, '')
34
34
  end
35
35
 
36
36
  def raw
@@ -53,10 +53,20 @@ class Fuse::Document::Asset
53
53
  def media
54
54
  @media ||= (match = MEDIA_PATTERN.match(path)) && match[1].split(/,\s*/).sort.join(', ')
55
55
  end
56
- def compress; ::Sass.compile raw, style: :compressed end
56
+ def compress
57
+ original = raw
58
+ compressed = ::Sass.compile original, style: :compressed
59
+ Fuse.log "SASS: Compressed #{path} from #{original.length} bytes to #{compressed.length} bytes", :success
60
+ compressed
61
+ end
57
62
  def type; 'text/css' end
58
63
  class Sass < self
59
- def filter; ::Sass.compile raw, style: :expanded end
64
+ def filter
65
+ original = raw
66
+ compiled = ::Sass.compile original, style: :expanded
67
+ Fuse.log "SASS: Compiled #{path} from #{original.length} bytes to #{compiled.length} bytes", :success
68
+ compiled
69
+ end
60
70
  end
61
71
  end
62
72
 
@@ -73,10 +83,20 @@ class Fuse::Document::Asset
73
83
  }
74
84
  }
75
85
  end
76
- def compress; Uglifier.compile filtered end
86
+ def compress
87
+ original = filtered
88
+ compressed = Uglifier.compile original
89
+ Fuse.log "Uglifier: Compressed #{path} from #{original.length} bytes to #{compressed.length} bytes", :success
90
+ compressed
91
+ end
77
92
  def type; 'text/javascript' end
78
93
  class Coffee < self
79
- def filter; CoffeeScript.compile raw end
94
+ def filter
95
+ original = raw
96
+ compiled = CoffeeScript.compile original
97
+ Fuse.log "CoffeeScript: Compiled #{path} from #{original.length} bytes to #{compiled.length} bytes", :success
98
+ compiled
99
+ end
80
100
  end
81
101
  end
82
102
 
data/lib/fuse/main.rb CHANGED
@@ -9,6 +9,7 @@ module Fuse
9
9
  encoding: 'UTF-8'
10
10
  },
11
11
  server: {
12
+ addr: '127.0.0.1',
12
13
  port: 9460,
13
14
  embed_assets: false
14
15
  },
@@ -18,19 +19,33 @@ module Fuse
18
19
  }
19
20
  }
20
21
 
22
+ SUMMARY_WIDTH = 30
23
+ SUMMARY_INDENT = 4
24
+
21
25
  def self.main
22
26
 
23
27
  options = {}
24
28
 
25
29
  options_parser = OptionParser.new do |opts|
26
30
 
27
- opts.banner = 'Usage: fuse [command] [options]'
28
- opts.separator ''
29
- opts.separator 'Commands:'
30
- opts.separator ' server : Run a local testing server'
31
- opts.separator ' compile : Compile the document and send to STDOUT'
32
- opts.separator ''
33
- opts.separator 'Options:'
31
+ "
32
+
33
+ Usage: #{$0} [command] [options]
34
+
35
+ Commands:
36
+ server : Run a local testing server
37
+ compile : Compile the document and send to STDOUT
38
+
39
+ Options:
40
+
41
+ ".strip.lines.each { |line| opts.separator line }
42
+
43
+ opts.on('-a',
44
+ '--addr',
45
+ wrap("Server binding address. Defaults to #{DEFAULTS[:server][:addr]}. Use 0.0.0.0 for access from other computers. Be careful; server will allow access to any locally accessible file of Fuse's supported types.")
46
+ ) do |addr|
47
+ options[:addr] = addr
48
+ end
34
49
 
35
50
  opts.on('-c',
36
51
  '--[no-]compress-assets',
@@ -41,7 +56,7 @@ module Fuse
41
56
 
42
57
  opts.on('-e',
43
58
  '--encoding CHARSET',
44
- "Output encoding. Default is #{DEFAULTS[:common][:encoding]}."
59
+ wrap("Output encoding. Default is #{DEFAULTS[:common][:encoding]}.")
45
60
  ) do |e|
46
61
  options[:encoding] = e
47
62
  end
@@ -56,14 +71,14 @@ module Fuse
56
71
  opts.on('-p',
57
72
  '--port PORT',
58
73
  Integer,
59
- "Port on which to listen (only with 'server' command). Default is #{DEFAULTS[:server][:port]}."
74
+ wrap("Port on which to listen (only with 'server' command). Default is #{DEFAULTS[:server][:port]}.")
60
75
  ) do |port|
61
76
  options[:port] = port
62
77
  end
63
78
 
64
79
  opts.on('-s',
65
80
  '--source [FILE|DIR]',
66
- 'The source directory, or HTML or XML document. Default is current directory.'
81
+ wrap('The source directory, or HTML or XML document. Default is current directory.')
67
82
  ) do |doc|
68
83
  options[:source] = doc
69
84
  end
@@ -82,13 +97,13 @@ module Fuse
82
97
 
83
98
  opts.on('-x',
84
99
  '--xsl FILE',
85
- 'XSL transformation stylesheet. Default is current directory.'
100
+ wrap('XSL transformation stylesheet. Default is current directory.')
86
101
  ) do |xsl|
87
102
  abort "#{xsl} isn't a valid XSL stylesheet" unless xsl.match(/\.xsl$/i)
88
103
  options[:xsl] = xsl
89
104
  end
90
105
 
91
- opts.on_tail('-h', '--help', 'Show this message.') { puts opts.to_s }
106
+ opts.on_tail('-h', '--help', 'Show this message.') { summary opts }
92
107
 
93
108
  end
94
109
 
@@ -99,23 +114,26 @@ module Fuse
99
114
  case ARGV[0]
100
115
 
101
116
  when 'server'
102
- Thin::Server.start('0.0.0.0', options[:port]) do
117
+ Thin::Server.start(options[:addr], options[:port]) do
103
118
  use Rack::ShowExceptions
104
119
  run Server.new(options)
105
120
  end
106
121
 
107
122
  when 'compile'
108
123
  begin
109
- print Document.new(options).to_s
124
+ doc = Document.new(options)
125
+ log "Compiling #{doc.source_path}"
126
+ print doc.to_s
127
+ log 'Done.', :success
110
128
  rescue Exception::SourceUnknown::TooManySources
111
- $stderr.puts "Found more than one potential #{$!.option_name} document. Please specify one with --#{$!.option_name}."
112
- $stderr.puts $!.options.join "\n"
129
+ log "Found more than one potential #{$!.option_name} document. Please specify one with --#{$!.option_name}.", :notice
130
+ log $!.options.join "\n"
113
131
  rescue Exception
114
- $!.message ? $stderr.puts($!.message) : raise
132
+ $!.message ? log($!.message, :error) : raise
115
133
  end
116
134
 
117
135
  else
118
- puts options_parser
136
+ summary options_parser
119
137
 
120
138
  end
121
139
 
@@ -131,4 +149,12 @@ module Fuse
131
149
  end
132
150
  end
133
151
 
152
+ def self.wrap(text, width = 80 - SUMMARY_WIDTH)
153
+ text.gsub(/(.{1,#{width}})(\s+|$)/, "\\1\n#{' ' * (SUMMARY_WIDTH + SUMMARY_INDENT + 1)}").strip
154
+ end
155
+
156
+ def self.summary(opts)
157
+ abort opts.summarize([], SUMMARY_WIDTH, SUMMARY_WIDTH - 1, ' ' * SUMMARY_INDENT).join
158
+ end
159
+
134
160
  end
data/lib/fuse/server.rb CHANGED
@@ -13,28 +13,39 @@ class Fuse::Server
13
13
  call_options = @options.merge Hash[request.GET.map{ |k, v| [k.to_sym, v] }]
14
14
 
15
15
  if @root && (asset = Fuse::Document::Asset.for(request.path))
16
+ log env, "Serve asset #{asset.path}"
16
17
  return asset.call(env)
17
18
  end
18
19
 
19
20
  begin
20
21
  doc = Fuse::Document.new(call_options)
21
22
  @root = doc.root
23
+ result = doc.to_s
24
+ log env, "Using #{doc.xsl_path} for transformation" if doc.xsl_path
25
+ log env, "Rendered #{doc.source_path} (#{result.length} bytes)", :success
22
26
  rescue Fuse::Exception::SourceUnknown::TooManySources
23
- doc = render_list($!.options, $!.option_name, request)
27
+ result = render_list($!.options, $!.option_name, request)
28
+ log env, 'Multiple source document options', :notice
24
29
  rescue Fuse::Exception
25
30
  if $!.message
26
- doc = render_error($!.message)
31
+ result = render_error($!.message)
32
+ log env, $!.message, :notice
27
33
  else
28
34
  raise
29
35
  end
30
36
  end
31
37
 
32
- [200, {'Content-Type' => 'text/html'}, [doc.to_s]]
38
+ [200, {'Content-Type' => 'text/html'}, [result]]
33
39
 
34
40
  end
35
41
 
36
42
  private
37
43
 
44
+ def log(env, message, *args)
45
+ Fuse.log_file.write "#{Time.now.strftime '%Y-%m-%d %H:%M:%S'} [#{env['REMOTE_ADDR']}] GET #{env['REQUEST_PATH']} "
46
+ Fuse.log message, *args
47
+ end
48
+
38
49
  def render_error(text)
39
50
  render_body do |h|
40
51
  h.p { h.text text }
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: fuse
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.3
4
+ version: 0.1.4
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2013-03-03 00:00:00.000000000 Z
12
+ date: 2013-03-05 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: thin