fuse 0.1.5 → 0.1.6

Sign up to get free protection for your applications and to get access to all the features.
@@ -3,7 +3,7 @@ require 'thin'
3
3
 
4
4
  module Fuse
5
5
 
6
- VERSION = '0.1.5'
6
+ VERSION = '0.1.6'
7
7
 
8
8
  LOG_COLOURS = {
9
9
  info: 6, # cyan
@@ -42,6 +42,10 @@ require 'fuse/exceptions'
42
42
  require 'fuse/server'
43
43
  require 'fuse/document'
44
44
  require 'fuse/document/asset'
45
+ require 'fuse/document/asset/has_dependents'
46
+ require 'fuse/document/asset/style_sheet'
47
+ require 'fuse/document/asset/java_script'
48
+ require 'fuse/document/asset/font'
45
49
  require 'fuse/document/asset_types'
46
50
  require 'fuse/document/asset_collection'
47
51
 
@@ -13,24 +13,29 @@ class Fuse::Document
13
13
  end
14
14
 
15
15
  def to_s
16
- result.to_html encoding: @options[:encoding]
16
+ ret = result.to_html encoding: @options[:encoding], indent: 0
17
+ ret.gsub!(/(\s)\s+/, '\\1') unless @options[:preserve_white]
18
+ ret
17
19
  end
18
20
 
19
21
  def result
20
22
 
21
- #todo find a way to transform Nokogiri XML to HTML without serializing
22
-
23
23
  document = if xsl_path
24
- Nokogiri::HTML(Nokogiri::XSLT(File.read xsl_path).transform(Nokogiri::XML(File.read source_path)).to_html encoding: @options[:encoding])
24
+ Nokogiri::XSLT(File.read xsl_path).transform(Nokogiri(File.read source_path))
25
25
  else
26
26
  Nokogiri::HTML(File.read source_path)
27
27
  end
28
28
 
29
- html = document.css('> html').first
29
+ while (html = document.css('> html').first).nil?
30
+ document = Nokogiri::HTML(document.to_html encoding: @options[:encoding])
31
+ end
30
32
  body = html.css('> body').first
31
33
  head = html.css('> head').first || body.add_previous_sibling(Nokogiri::XML::Node.new 'head', document)
32
34
 
33
- document.title = @options[:title] unless @options[:title].nil?
35
+ unless @options[:title].nil?
36
+ title = head.css('> title').first || head.add_child(Nokogiri::XML::Node.new('title', document))
37
+ title.children = Nokogiri::XML::Text.new(@options[:title], document)
38
+ end
34
39
 
35
40
  #attach stylesheets and scripts
36
41
  [Fuse::Document::Asset::StyleSheet, Fuse::Document::Asset::JavaScript].each do |klass|
@@ -0,0 +1,32 @@
1
+ class Fuse::Document::Asset
2
+ class Font < self
3
+ CSS_FORMATS = [
4
+ { extension: :woff, format: 'woff' },
5
+ { extension: :ttf, format: 'truetype' },
6
+ { extension: :otf, format: 'opentype' }
7
+ ]
8
+ MIME_TYPES = {
9
+ otf: 'application/x-font-opentype',
10
+ ttf: 'application/x-font-truetype',
11
+ woff: 'application/x-font-woff'
12
+ }
13
+ VARIANT_PATTERN = %r`([^/]+?)(?:[-_ ](normal|bold|bolder|lighter|[1-9]00))?(?:[-_ ](normal|italic|oblique))?\.[a-z]+$`
14
+ def family; @family ||= variant[:family] end
15
+ def weight; @weight ||= variant[:weight] end
16
+ def style; @style ||= variant[:style] end
17
+ def variant
18
+ @variant ||= begin
19
+ match = VARIANT_PATTERN.match(path)
20
+ {
21
+ family: match[1],
22
+ weight: match[2] || 'normal',
23
+ style: match[3] || 'normal'
24
+ }
25
+ end
26
+ end
27
+ def face; @face ||= [family, weight, style].join('-') end
28
+ def type
29
+ MIME_TYPES[extension.to_sym] || super
30
+ end
31
+ end
32
+ end
@@ -0,0 +1,31 @@
1
+ module Fuse::Document::Asset::HasDependents
2
+
3
+ COMMENT_PATTERN = %r`^\s*(/\*[\s\S]*?\*/|(\s*//.*\s+)+)`
4
+ REQUIRE_PATTERN = %r`^\s*(?:\*|//)=\s+(require|require_glob)\s+(.+?)\s*$`
5
+
6
+ def dependents
7
+ ret = Fuse::Document::AssetCollection.new
8
+ local_root = File.dirname(full_path)
9
+ if (comments = raw[COMMENT_PATTERN])
10
+ comments.lines.each do |line|
11
+ if (match = REQUIRE_PATTERN.match(line))
12
+ case match[1]
13
+ when 'require'
14
+ [File.join(local_root, match[2])]
15
+ when 'require_glob'
16
+ Dir[File.join(local_root, match[2])]
17
+ else
18
+ []
19
+ end.map do |p|
20
+ Fuse::Document::Asset.for(p[@root.length..-1], @root)
21
+ end.reject do |p|
22
+ p.nil?
23
+ end.each do |p|
24
+ ret << p
25
+ end
26
+ end
27
+ end
28
+ end
29
+ ret
30
+ end
31
+ end
@@ -0,0 +1,32 @@
1
+ class Fuse::Document::Asset
2
+ class JavaScript < self
3
+ EMBED_WITH = 'script'
4
+ JOIN_WITH = ';'
5
+ include HasDependents
6
+ def reference_with
7
+ {
8
+ tag_name: 'script',
9
+ attributes: {
10
+ type: type,
11
+ src: relative_path
12
+ }
13
+ }
14
+ end
15
+ def compress
16
+ original = filtered
17
+ compressed = Uglifier.compile original
18
+ Fuse.log "Uglifier: Compressed #{path} from #{original.bytesize} bytes to #{compressed.bytesize} bytes", :success
19
+ compressed
20
+ end
21
+ def type; 'text/javascript' end
22
+ class Coffee < self
23
+ def filter
24
+ original = raw
25
+ compiled = CoffeeScript.compile original
26
+ Fuse.log "CoffeeScript: Compiled #{path} from #{original.bytesize} bytes to #{compiled.bytesize} bytes", :success
27
+ compiled
28
+ end
29
+ end
30
+ end
31
+
32
+ end
@@ -0,0 +1,36 @@
1
+ class Fuse::Document::Asset
2
+ class StyleSheet < self
3
+ EMBED_WITH = 'style'
4
+ JOIN_WITH = ''
5
+ MEDIA_PATTERN = /\(([a-z]+(?:,\s*[a-z]+)*)\)\.[a-z]+$/i
6
+ include HasDependents
7
+ def reference_with
8
+ {
9
+ tag_name: 'link',
10
+ attributes: {
11
+ rel: 'stylesheet',
12
+ href: relative_path,
13
+ media: media
14
+ }
15
+ }
16
+ end
17
+ def media
18
+ @media ||= (match = MEDIA_PATTERN.match(path)) && match[1].split(/,\s*/).sort.join(', ')
19
+ end
20
+ def compress
21
+ original = raw
22
+ compressed = ::Sass.compile original, style: :compressed
23
+ Fuse.log "SASS: Compressed #{path} from #{original.bytesize} bytes to #{compressed.bytesize} bytes", :success
24
+ compressed
25
+ end
26
+ def type; 'text/css' end
27
+ class Sass < self
28
+ def filter
29
+ original = raw
30
+ compiled = ::Sass.compile original, style: :expanded
31
+ Fuse.log "SASS: Compiled #{path} from #{original.bytesize} bytes to #{compiled.bytesize} bytes", :success
32
+ compiled
33
+ end
34
+ end
35
+ end
36
+ end
@@ -4,136 +4,9 @@ require 'uglifier'
4
4
 
5
5
  class Fuse::Document::Asset
6
6
 
7
- module HasDependents
8
- COMMENT_PATTERN = %r`^\s*(/\*[\s\S]*?\*/|(\s*//.*\s+)+)`
9
- REQUIRE_PATTERN = %r`^\s*(?:\*|//)=\s+(require|require_glob)\s+(.+?)\s*$`
10
-
11
- def dependents
12
- ret = Fuse::Document::AssetCollection.new
13
- local_root = File.dirname(full_path)
14
- if (comments = raw[COMMENT_PATTERN])
15
- comments.lines.each do |line|
16
- if (match = REQUIRE_PATTERN.match(line))
17
- case match[1]
18
- when 'require'
19
- [File.join(local_root, match[2])]
20
- when 'require_glob'
21
- Dir[File.join(local_root, match[2])]
22
- else
23
- []
24
- end.map do |p|
25
- Fuse::Document::Asset.for(p[@root.length..-1], @root)
26
- end.reject do |p|
27
- p.nil?
28
- end.each do |p|
29
- ret << p
30
- end
31
- end
32
- end
33
- end
34
- ret
35
- end
36
- end
37
-
38
- class StyleSheet < self
39
- EMBED_WITH = 'style'
40
- JOIN_WITH = ''
41
- MEDIA_PATTERN = /\(([a-z]+(?:,\s*[a-z]+)*)\)\.[a-z]+$/i
42
- include HasDependents
43
- def reference_with
44
- {
45
- tag_name: 'link',
46
- attributes: {
47
- rel: 'stylesheet',
48
- href: relative_path,
49
- media: media
50
- }
51
- }
52
- end
53
- def media
54
- @media ||= (match = MEDIA_PATTERN.match(path)) && match[1].split(/,\s*/).sort.join(', ')
55
- 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
62
- def type; 'text/css' end
63
- class Sass < self
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
70
- end
71
- end
72
-
73
- class JavaScript < self
74
- EMBED_WITH = 'script'
75
- JOIN_WITH = ';'
76
- include HasDependents
77
- def reference_with
78
- {
79
- tag_name: 'script',
80
- attributes: {
81
- type: type,
82
- src: relative_path
83
- }
84
- }
85
- 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
92
- def type; 'text/javascript' end
93
- class Coffee < self
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
100
- end
101
- end
102
-
103
7
  class Image < self
104
8
  end
105
9
 
106
- class Font < self
107
- CSS_FORMATS = [
108
- { extension: :woff, format: 'woff' },
109
- { extension: :ttf, format: 'truetype' },
110
- { extension: :otf, format: 'opentype' }
111
- ]
112
- MIME_TYPES = {
113
- otf: 'application/x-font-opentype',
114
- ttf: 'application/x-font-truetype',
115
- woff: 'application/x-font-woff'
116
- }
117
- VARIANT_PATTERN = %r`([^/]+?)(?:[-_ ](normal|bold|bolder|lighter|[1-9]00))?(?:[-_ ](normal|italic|oblique))?\.[a-z]+$`
118
- def family; @family ||= variant[:family] end
119
- def weight; @weight ||= variant[:weight] end
120
- def style; @style ||= variant[:style] end
121
- def variant
122
- @variant ||= begin
123
- match = VARIANT_PATTERN.match(path)
124
- {
125
- family: match[1],
126
- weight: match[2] || 'normal',
127
- style: match[3] || 'normal'
128
- }
129
- end
130
- end
131
- def face; @face ||= [family, weight, style].join('-') end
132
- def type
133
- MIME_TYPES[extension.to_sym] || super
134
- end
135
- end
136
-
137
10
  class Xml < self
138
11
  end
139
12
 
@@ -6,7 +6,8 @@ module Fuse
6
6
  DEFAULTS = {
7
7
  common: {
8
8
  source: '.',
9
- encoding: 'UTF-8'
9
+ encoding: 'UTF-8',
10
+ preserve_white: true
10
11
  },
11
12
  server: {
12
13
  addr: '127.0.0.1',
@@ -30,7 +31,7 @@ module Fuse
30
31
 
31
32
  "
32
33
 
33
- Usage: #{$0} [command] [options]
34
+ Usage: #{$0} command [options]
34
35
 
35
36
  Commands:
36
37
  server : Run a local testing server
@@ -95,6 +96,11 @@ Options:
95
96
  'Show Fuse version.'
96
97
  ) { abort Fuse::VERSION }
97
98
 
99
+ opts.on('-w',
100
+ '--[no-]preserve-white',
101
+ wrap("Preserve all white space in HTML. Default is #{DEFAULTS[:common][:preserve_white]}.")
102
+ ) { |w| options[:preserve_white] = w }
103
+
98
104
  opts.on('-x',
99
105
  '--xsl FILE',
100
106
  wrap('XSL transformation stylesheet. Default is current directory.')
@@ -123,8 +129,9 @@ Options:
123
129
  begin
124
130
  doc = Document.new(options)
125
131
  log "Compiling #{doc.source_path}"
126
- print doc.to_s
127
- log 'Done.', :success
132
+ out = doc.to_s
133
+ print out
134
+ log "Wrote #{out.bytesize} byte(s) to STDOUT.", :success
128
135
  rescue Exception::SourceUnknown::TooManySources
129
136
  log "Found more than one potential #{$!.option_name} document. Please specify one with --#{$!.option_name}.", :notice
130
137
  log $!.options.join "\n"
@@ -4,6 +4,7 @@ class Fuse::Server
4
4
 
5
5
  def initialize(options)
6
6
  @options = options
7
+ Fuse.log "Starting Fuse Server v#{Fuse::VERSION}", :success
7
8
  end
8
9
 
9
10
  def call(env)
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.5
4
+ version: 0.1.6
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-07 00:00:00.000000000 Z
12
+ date: 2013-03-11 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: thin
@@ -134,6 +134,10 @@ extensions: []
134
134
  extra_rdoc_files: []
135
135
  files:
136
136
  - bin/fuse
137
+ - lib/fuse/document/asset/font.rb
138
+ - lib/fuse/document/asset/has_dependents.rb
139
+ - lib/fuse/document/asset/java_script.rb
140
+ - lib/fuse/document/asset/style_sheet.rb
137
141
  - lib/fuse/document/asset.rb
138
142
  - lib/fuse/document/asset_collection.rb
139
143
  - lib/fuse/document/asset_types.rb