distil 0.10.4 → 0.11.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.
Files changed (63) hide show
  1. data/Rakefile +2 -1
  2. data/VERSION +1 -1
  3. data/assets/distil.js +359 -0
  4. data/bin/distil +33 -10
  5. data/distil.gemspec +35 -24
  6. data/lib/distil/configurable/file-set.rb +86 -0
  7. data/lib/distil/configurable/interpolated.rb +36 -0
  8. data/lib/distil/configurable/output-path.rb +25 -0
  9. data/lib/distil/configurable/project-path.rb +25 -0
  10. data/lib/distil/configurable.rb +164 -0
  11. data/lib/distil/error-reporter.rb +63 -0
  12. data/lib/distil/product/concatenated.rb +85 -0
  13. data/lib/distil/product/css-product.rb +37 -0
  14. data/lib/distil/product/debug.rb +34 -0
  15. data/lib/distil/product/javascript-base-product.rb +35 -0
  16. data/lib/distil/product/javascript-doc-product.rb +61 -0
  17. data/lib/distil/product/javascript-product.rb +131 -0
  18. data/lib/distil/product/minified.rb +32 -0
  19. data/lib/distil/product.rb +97 -0
  20. data/lib/distil/project/distil-project.rb +99 -0
  21. data/lib/distil/project/external-project.rb +53 -0
  22. data/lib/distil/project.rb +78 -0
  23. data/lib/distil/source-file/css-file.rb +14 -0
  24. data/lib/distil/source-file/html-file.rb +14 -0
  25. data/lib/distil/source-file/javascript-file.rb +17 -0
  26. data/lib/distil/source-file/json-file.rb +16 -0
  27. data/lib/distil/source-file.rb +172 -0
  28. data/lib/distil/target.rb +235 -0
  29. data/lib/distil/task/css-dependency-task.rb +64 -0
  30. data/lib/distil/task/jsl-dependency-task.rb +49 -0
  31. data/lib/distil/task/nib-task.rb +72 -0
  32. data/lib/distil/task/validate-js-task.rb +75 -0
  33. data/lib/distil/task.rb +50 -0
  34. data/lib/distil.rb +72 -0
  35. data/lib/jsl.conf +4 -0
  36. data/vendor/jsl-0.3.0/src/Makefile.ref +16 -6
  37. data/vendor/jsl-0.3.0/src/config.mk +32 -2
  38. data/vendor/jsl-0.3.0/src/fdlibm/Makefile.ref +1 -2
  39. data/vendor/jsl-0.3.0/src/jsl.c +124 -13
  40. data/vendor/jsl-0.3.0/src/rules.mk +2 -1
  41. metadata +49 -28
  42. data/lib/bootstrap-template.js +0 -58
  43. data/lib/configurable.rb +0 -161
  44. data/lib/file-set.rb +0 -49
  45. data/lib/file-types/css-file.rb +0 -12
  46. data/lib/file-types/html-file.rb +0 -11
  47. data/lib/file-types/javascript-file.rb +0 -24
  48. data/lib/file-types/json-file.rb +0 -17
  49. data/lib/filter.rb +0 -41
  50. data/lib/filters/css-filter.rb +0 -58
  51. data/lib/filters/file-reference-filter.rb +0 -30
  52. data/lib/filters/jsl-dependency-filter.rb +0 -44
  53. data/lib/project.rb +0 -174
  54. data/lib/source-file.rb +0 -197
  55. data/lib/target.rb +0 -102
  56. data/lib/task.rb +0 -212
  57. data/lib/tasks/copy-task.rb +0 -17
  58. data/lib/tasks/css-task.rb +0 -12
  59. data/lib/tasks/javascript-task.rb +0 -206
  60. data/lib/tasks/multiple-output-task.rb +0 -140
  61. data/lib/tasks/output-task.rb +0 -76
  62. data/lib/tasks/single-output-task.rb +0 -104
  63. data/lib/tasks/test-task.rb +0 -280
@@ -1,24 +0,0 @@
1
- $jsl_import_regex= /\/\*jsl:import\s+([^\*]*)\*\//
2
- $include_regex= /NIB\.asset\(['"]([^)]+)['"]\)/
3
-
4
- class JavascriptFile < SourceFile
5
-
6
- def self.extension
7
- ".js"
8
- end
9
-
10
- def can_embed_as_content(file)
11
- [".css", ".html", ".json"].include?(file.extension)
12
- end
13
-
14
- def escape_embeded_content(content)
15
- content.gsub("\\", "\\\\").gsub("\n", "\\n").gsub("\"", "\\\"").gsub("'", "\\\\'")
16
- end
17
-
18
- def debug_content(options)
19
- destination= File.expand_path(options.remove_prefix||"")
20
- path= @file_path ? @file_path : self.relative_to_folder(destination)
21
- "loadScript(\"#{path}\");\n"
22
- end
23
-
24
- end
@@ -1,17 +0,0 @@
1
- require "#{$script_dir}/file-types/javascript-file.rb"
2
-
3
- class JsonFile < JavascriptFile
4
-
5
- def self.extension
6
- ".json"
7
- end
8
-
9
- def content_type
10
- "js"
11
- end
12
-
13
- def minify_content(source)
14
- super("(#{source})")[1..-3]
15
- end
16
-
17
- end
data/lib/filter.rb DELETED
@@ -1,41 +0,0 @@
1
- # require "#{$script_dir}/configurable"
2
-
3
- class Filter
4
-
5
- @@filters= []
6
- def self.inherited(subclass)
7
- @@filters << subclass.new
8
- end
9
-
10
- def self.abstract
11
- false
12
- end
13
-
14
- def self.each
15
- @@filters.each { |f|
16
- yield f
17
- }
18
- end
19
-
20
- def self.defined
21
- @@filters
22
- end
23
-
24
- def handles_file(file)
25
- false
26
- end
27
-
28
- def preprocess_content(file, content)
29
- content
30
- end
31
-
32
- def filter_content(file, content, options={})
33
- content
34
- end
35
-
36
- end
37
-
38
- # load all the other file types
39
- Dir.glob("#{$script_dir}/filters/*-filter.rb") { |file|
40
- require file
41
- }
@@ -1,58 +0,0 @@
1
- require "#{$script_dir}/filters/file-reference-filter"
2
-
3
- $jsl_import_regex= /\/\*jsl:import\s+([^\*]*)\*\//
4
-
5
- class CssDependencyFilter < FileReferenceFilter
6
-
7
- def handles_file(file)
8
- return ["css"].include?(file.content_type)
9
- end
10
-
11
- def preprocess_content(file, content)
12
- # Replace all ' (single quotes) with " (double quotes) in
13
- # order to fix a problem with the background url regexp
14
- content.gsub!(/\'/,'"')
15
- # Force a newline after a rule terminating ; (semi-colon)
16
- # in order to fix a problem with the background url regexp
17
- content.gsub!(/;(\n|\r)*/, ";\n")
18
-
19
- # Rewrites the 'url("...")' rules to a relative path
20
- # based on the location of the new concatenated CSS file.
21
- line_num=0
22
-
23
- lines= content.split("\n")
24
-
25
- lines.each { |line|
26
-
27
- line_num+=1
28
-
29
- line.gsub!(/@import\s+url\("?(.*\.css)"?\)/) { |match|
30
- css_file= File.join(file.parent_folder, $1)
31
-
32
- if (!File.exists?(css_file))
33
- file.error "imported CSS file not found: #{$1}", line_num
34
- # leave the @import rule in place
35
- match
36
- else
37
- file.add_dependency(SourceFile.from_path(css_file))
38
- end
39
- }
40
-
41
- line.gsub!(/url\("?(.*\.(jpg|png|gif))"?\)/) { |match|
42
- image_file= File.join(file.parent_folder, $1)
43
-
44
- if (!File.exists?(image_file))
45
- file.warning "resource not found: #{$1} (#{image_file})", line_num
46
- "url(\"#{$1}\")"
47
- else
48
- asset= SourceFile.from_path(image_file)
49
- file.add_asset(asset)
50
- "url(\"#{file_reference(asset)}\")"
51
- end
52
- }
53
- }
54
-
55
- lines.join("\n")
56
- end
57
-
58
- end
@@ -1,30 +0,0 @@
1
- class FileReferenceFilter < Filter
2
-
3
- def file_reference(file)
4
- "{{FILEREF(#{file})}}"
5
- end
6
-
7
- def content_reference(file)
8
- "{{CONTENTREF(#{file})}}"
9
- end
10
-
11
- def filter_content(file, content, options)
12
- destination= File.expand_path(options.remove_prefix||"")
13
-
14
- content.gsub!(/\{\{FILEREF\(([^)]*)\)\}\}/) { |match|
15
- include_file= SourceFile.from_path($1)
16
- include_file.relative_to_folder(destination)
17
- }
18
-
19
- content.gsub!(/\{\{CONTENTREF\(([^)]*)\)\}\}/) { |match|
20
- include_file= SourceFile.from_path($1)
21
- included_content= include_file.filtered_content(options)
22
- included_content= include_file.minify_content(included_content)
23
- file.escape_embeded_content(included_content)
24
- }
25
-
26
- content
27
- end
28
-
29
-
30
- end
@@ -1,44 +0,0 @@
1
- $jsl_import_regex= /\/\*jsl:import\s+([^\*]*)\*\//
2
-
3
- class JslDependencyFilter < Filter
4
-
5
- def handles_file(file)
6
- return ["js"].include?(file.content_type)
7
- end
8
-
9
- def preprocess_content(file, content)
10
-
11
- content= content.split("\n")
12
-
13
- line_num=0
14
-
15
- content.each { |line|
16
-
17
- line_num+=1
18
-
19
- # handle dependencies
20
- line.gsub!($jsl_import_regex) { |match|
21
-
22
- import_file= File.expand_path(File.join(file.parent_folder, $1))
23
- if (File.exists?(import_file))
24
- file.add_dependency SourceFile.from_path(import_file)
25
- else
26
- dependency= Project.current.find_file($1)
27
- if (dependency)
28
- file.add_dependency dependency
29
- else
30
- file.error "Missing import file: #{$1}", line_num
31
- end
32
- end
33
-
34
- # replace jsl import with empty string
35
- ""
36
-
37
- }
38
-
39
- }
40
-
41
- content.join("\n")
42
- end
43
-
44
- end
data/lib/project.rb DELETED
@@ -1,174 +0,0 @@
1
- require "#{$script_dir}/target"
2
-
3
- require 'yaml'
4
-
5
- class Project < Configurable
6
- attr_reader :project_file
7
-
8
- option :tasks, Array
9
- option_alias :tasks, :task
10
-
11
- option :version, String
12
- option :project_name, String
13
- option_alias :project_name, :name
14
-
15
- option :targets, Array
16
- option_alias :targets, :target
17
-
18
- option :mode
19
- option :ignore_warnings, false
20
-
21
- option :external_projects
22
-
23
- option :distileries, Array
24
- option_alias :distileries, :distilleries
25
- option_alias :distileries, :distilery
26
- option_alias :distileries, :distillery
27
-
28
-
29
- def initialize(project_file, settings)
30
- @@current= self
31
- @project_file= File.expand_path(project_file)
32
- Dir.chdir(File.dirname(@project_file))
33
-
34
- project_info= YAML.load_file(@project_file)
35
- settings.merge!(project_info)
36
- super(settings)
37
- end
38
-
39
- @@current=nil
40
- def self.current
41
- @@current
42
- end
43
-
44
- def find_file(file)
45
- return nil if external_projects.nil?
46
-
47
- external_projects.each { |project|
48
- path= File.expand_path(File.join(project["include"], file))
49
- if (File.exists?(path))
50
- source_file= SourceFile.from_path(path)
51
- source_file.file_path= file
52
- return source_file
53
- end
54
- }
55
- nil
56
- end
57
-
58
- def build
59
- load_distileries
60
- build_external_projects
61
- build_targets
62
- end
63
-
64
- def load_distileries
65
- return if distileries.nil?
66
-
67
- distileries.each { |d|
68
- if (File.exists?(d))
69
- require d
70
- next
71
- end
72
- path= Gem.required_location(d, 'distilery.rb')
73
- if (path.nil?)
74
- puts "Missing distilery: #{d}"
75
- end
76
- next if path.nil?
77
- require path
78
- }
79
- end
80
-
81
- def build_external_projects
82
- projects= external_projects
83
- if (projects.nil?)
84
- @options.external_projects= []
85
- return
86
- end
87
-
88
- # Handle external projects
89
- if (projects.is_a?(String))
90
- projects= projects.split(/\s*,\s*/)
91
- end
92
-
93
- if (projects.is_a?(Array))
94
- projects= projects.map { |folder|
95
- {
96
- "folder"=>folder
97
- }
98
- }
99
- else
100
- projects= projects.map { |folder, project|
101
-
102
- if project.is_a?(String)
103
- project= {
104
- "url"=>project
105
- }
106
- end
107
-
108
- defaults= {
109
- "folder"=>folder,
110
- "build"=>"distil",
111
- "include"=>File.join(folder, "build")
112
- }
113
-
114
- defaults.merge(project)
115
- }
116
- end
117
-
118
- # build or get each project
119
- projects.each { |project|
120
-
121
- if (project.key?("folder") && !File.directory?(project["folder"]) && !File.symlink?(project["folder"]))
122
- if (project["url"])
123
- url= project["url"]
124
- system "svn co #{url} #{project["folder"]}"
125
- else
126
- puts "#{@project_file}: external project folder missing: #{project["folder"]}"
127
- exit
128
- end
129
- end
130
-
131
- if (!project.key?("include"))
132
- project["include"]= File.join(project["folder"], "build")
133
- end
134
-
135
- build= project["build"] || "distil"
136
- wd= Dir.pwd
137
- Dir.chdir(project["folder"]||project["include"])
138
- # pass along mode flag to sub-projects
139
- if (mode)
140
- build= "#{build} -mode=#{mode}"
141
- end
142
- system(build)
143
- Dir.chdir(wd)
144
- }
145
-
146
- @options.external_projects= projects
147
- end
148
-
149
- def build_targets
150
-
151
- @extras.each { |section, value|
152
-
153
- next if (options.targets && !options.targets.include?(section))
154
- next if ((!options.targets || !options.targets.include?(section)) &&
155
- value.is_a?(Hash) && value.has_key?("enabled") && !value["enabled"])
156
-
157
- puts
158
- puts "#{project_name}/#{section}:"
159
- puts
160
-
161
- task= Task.by_name(section) || Task.by_product_name(section)
162
- if (task)
163
- new_value= Hash.new
164
- new_value[section]= value
165
- value= new_value
166
- section= "all"
167
- end
168
-
169
- target= Target.new(section, value, self)
170
- target.process_files
171
- target.finish
172
- }
173
- end
174
- end
data/lib/source-file.rb DELETED
@@ -1,197 +0,0 @@
1
- require 'fileutils'
2
-
3
- $compressor = "#{$script_dir}/yuicompressor-2.4.2.jar"
4
-
5
- class SourceFile
6
- attr_accessor :parent_folder, :full_path
7
-
8
- def initialize(filepath)
9
- @full_path= File.expand_path(filepath)
10
-
11
- @parent_folder= File.dirname(@full_path)
12
- @dependencies= []
13
- @assets= []
14
-
15
- @@file_cache[@full_path]= self
16
- end
17
-
18
- def self.extension
19
- end
20
-
21
- def extension
22
- self.class.extension
23
- end
24
-
25
- def can_embed_as_content(file)
26
- false
27
- end
28
-
29
- def content_type
30
- ext= self.extension
31
- return if !ext
32
- ext[1..-1]
33
- end
34
-
35
- @@file_types= []
36
- def self.inherited(subclass)
37
- @@file_types << subclass
38
- end
39
-
40
- def self.file_types
41
- @@file_types
42
- end
43
-
44
- @@file_cache= Hash.new
45
- def self.from_path(filepath)
46
- full_path= File.expand_path(filepath)
47
- file= @@file_cache[full_path]
48
- return file if file
49
-
50
- extension= File.extname(filepath)
51
-
52
- @@file_types.each { |handler|
53
- next if (handler.extension != extension)
54
-
55
- return handler.new(filepath)
56
- }
57
-
58
- return SourceFile.new(filepath)
59
- end
60
-
61
- def to_s
62
- @full_path
63
- end
64
-
65
- def to_str
66
- @full_path
67
- end
68
-
69
- def error(message, line_number=0)
70
- Target.current.error(message, self, line_number)
71
- end
72
-
73
- def warning(message, line_number=0)
74
- Target.current.warning(message, self, line_number)
75
- end
76
-
77
- def basename(suffix="")
78
- File.basename(@full_path, suffix)
79
- end
80
-
81
- def file_path
82
- @file_path
83
- end
84
-
85
- def file_path=(path)
86
- @file_path=path
87
- end
88
-
89
- def load_content
90
- content= File.read(@full_path)
91
- Filter.each { |f|
92
- next if !f.handles_file(self)
93
- content= f.preprocess_content(self, content)
94
- }
95
- content
96
- end
97
-
98
- def escape_embeded_content(content)
99
- content
100
- end
101
-
102
- def content
103
- @content ||= load_content
104
- end
105
-
106
- def filtered_content(options)
107
- c= content || ""
108
- Filter.each { |f|
109
- next if !f.handles_file(self)
110
- c= f.filter_content(self, c, options)
111
- }
112
- c
113
- end
114
-
115
- def debug_content(options)
116
- self.filtered_content(options)
117
- end
118
-
119
- def minify_content(source)
120
- # Run the Y!UI Compressor
121
- return source if !content_type
122
- buffer= ""
123
-
124
- IO.popen("java -jar #{$compressor} --type #{content_type}", "r+") { |pipe|
125
- pipe.puts(source)
126
- pipe.close_write
127
- buffer= pipe.read
128
- }
129
-
130
- # buffer = `java -jar #{$compressor} --type #{type} #{working_file}`
131
- if ('css'==content_type)
132
- # puts each rule on its own line, and deletes @import statements
133
- return buffer.gsub(/\}/,"}\n").gsub(/.*@import url\(\".*\"\);/,'')
134
- else
135
- return buffer
136
- end
137
- end
138
-
139
- def self.path_relative_to_folder(path, folder)
140
- outputFolder= File.expand_path(folder).to_s
141
-
142
- # Remove leading slash and split into parts
143
- file_parts= path.slice(1..-1).split('/');
144
- output_parts= outputFolder.slice(1..-1).split('/');
145
-
146
- common_prefix_length= 0
147
-
148
- file_parts.each_index { |i|
149
- common_prefix_length= i
150
- break if file_parts[i]!=output_parts[i]
151
- }
152
-
153
- return '../'*(output_parts.length-common_prefix_length) + file_parts[common_prefix_length..-1].join('/')
154
- end
155
-
156
- def relative_to_folder(output_folder)
157
- self.class.path_relative_to_folder(@full_path, output_folder)
158
- end
159
-
160
- def relative_to_file(source_file)
161
- folder= File.dirname(File.expand_path(source_file))
162
- self.relative_to_folder(folder)
163
- end
164
-
165
- def dependencies
166
- content
167
- @dependencies
168
- end
169
-
170
- def add_dependency(file)
171
- return if @dependencies.include?(file)
172
- @dependencies << file
173
- end
174
-
175
- def assets
176
- content
177
- @assets
178
- end
179
-
180
- def add_asset(file)
181
- @assets << file
182
- end
183
-
184
- def copy_to(folder, prefix)
185
- file_path= self.file_path || relative_to_folder(prefix||"")
186
- final_target_folder= File.join(folder, File.dirname(file_path))
187
- FileUtils.mkdir_p final_target_folder
188
- FileUtils.cp self.full_path, final_target_folder
189
- File.join(final_target_folder, File.basename(file_path))
190
- end
191
-
192
- end
193
-
194
- # load all the other file types
195
- Dir.glob("#{$script_dir}/file-types/*-file.rb") { |file|
196
- require file
197
- }
data/lib/target.rb DELETED
@@ -1,102 +0,0 @@
1
- require "#{$script_dir}/task"
2
- require "set"
3
-
4
- class Target < Configurable
5
- attr_accessor :target_name, :warning_count, :error_count
6
-
7
- option :tasks, Array
8
-
9
- def initialize(name, settings, project)
10
- super(settings, project)
11
-
12
- @@current= self
13
- @project= project
14
- @target_name= name
15
-
16
- @warning_count=0
17
- @error_count=0
18
-
19
- @tasks= []
20
-
21
- @extras.each { |task_name, task_settings|
22
- next if (tasks && !tasks.include?(task_name))
23
-
24
- if (task_settings.is_a?(Array) || task_settings.is_a?(String))
25
- task_settings= { "include"=>task_settings }
26
- end
27
-
28
- t= Task.by_name(task_name)
29
- if (!t.nil?)
30
- @tasks << t.new(self, task_settings)
31
- next
32
- end
33
-
34
- t= Task.by_product_name(task_name)
35
- if (!t.nil?)
36
- task_settings["output_name"]= task_name[/(.*)\.#{t.output_type}$/,1]
37
- @tasks << t.new(self, task_settings)
38
- next
39
- end
40
-
41
- error("Unknown task: #{task_name}")
42
- }
43
- end
44
-
45
- @@current=nil
46
- def self.current
47
- @@current
48
- end
49
-
50
- def error(message, file="", line_number=0)
51
- @error_count+=1
52
- if (file && line_number)
53
- printf("%s:%d: error: %s\n", file, line_number, message)
54
- else
55
- printf("error: %s\n", message)
56
- end
57
- end
58
-
59
- def warning(message, file="", line_number=0)
60
- @warning_count+=1
61
- return if (ignore_warnings)
62
- if (file && line_number)
63
- printf("%s:%d: warning: %s\n", file, line_number, message)
64
- else
65
- printf("warning: %s\n", message)
66
- end
67
- end
68
-
69
- def products
70
- products= []
71
- @tasks.each { |task|
72
- products.concat(task.products)
73
- }
74
- products
75
- end
76
-
77
- def process_files
78
- @tasks.each { |t|
79
- t.find_files
80
-
81
- next if !t.need_to_build
82
-
83
- t.validate_files
84
- t.document_files
85
- t.process_files
86
- }
87
- end
88
-
89
- def finish
90
- @tasks.each { |t|
91
- t.finish if t.need_to_build
92
- t.build_assets
93
- }
94
-
95
- @tasks.each { |t|
96
- t.cleanup
97
- }
98
-
99
- puts "#{@error_count} error(s), #{@warning_count} warning(s)#{ignore_warnings ? " ignored" : ""}"
100
- end
101
-
102
- end