rill 0.0.1
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/bin/rill +50 -0
- data/lib/rill.rb +166 -0
- metadata +47 -0
data/bin/rill
ADDED
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
#!/usr/bin/env ruby
|
|
2
|
+
|
|
3
|
+
require 'rill'
|
|
4
|
+
require 'optparse'
|
|
5
|
+
|
|
6
|
+
options = {}
|
|
7
|
+
parser = OptionParser.new do |opts|
|
|
8
|
+
opts.banner = "Usage: rill --files foo,bar [options]"
|
|
9
|
+
|
|
10
|
+
opts.on('-f', '--files FILES', Array, 'Files to be polished') do |files|
|
|
11
|
+
options[:files] = files
|
|
12
|
+
end
|
|
13
|
+
opts.on('-b', '--base [BASE]', 'Base directory') do |path|
|
|
14
|
+
options[:base] = path
|
|
15
|
+
end
|
|
16
|
+
opts.on('-p', '--preloads [PRELOADS]', Array, 'Modules to be preloaded') do |preloads|
|
|
17
|
+
options[:preloads] = preloads.nil? ? [] : preloads
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
begin
|
|
22
|
+
parser.parse!
|
|
23
|
+
raise OptionParser::MissingArgument if options[:files].nil?
|
|
24
|
+
rescue OptionParser::InvalidOption, OptionParser::MissingArgument
|
|
25
|
+
puts $!
|
|
26
|
+
puts parser
|
|
27
|
+
exit
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
rill = Rill.new(:base => options[:base],
|
|
31
|
+
:preloads => options[:preloads])
|
|
32
|
+
|
|
33
|
+
options[:files].each do |f|
|
|
34
|
+
base = options[:base] || '.'
|
|
35
|
+
base = File.expand_path(base, Dir.pwd)
|
|
36
|
+
abort("Cann't find base directory #{path}") unless File.directory?(base)
|
|
37
|
+
pattern = File.expand_path(f, base)
|
|
38
|
+
|
|
39
|
+
files = Dir.glob(pattern)
|
|
40
|
+
if files.length == 0
|
|
41
|
+
puts "No files matches #{f}"
|
|
42
|
+
next
|
|
43
|
+
else
|
|
44
|
+
files.each do |f|
|
|
45
|
+
mod = f.sub(base, '').sub(/^\//, '')
|
|
46
|
+
rill.polish(mod)
|
|
47
|
+
puts "Polished #{mod}"
|
|
48
|
+
end
|
|
49
|
+
end
|
|
50
|
+
end
|
data/lib/rill.rb
ADDED
|
@@ -0,0 +1,166 @@
|
|
|
1
|
+
class Rill
|
|
2
|
+
|
|
3
|
+
DEFAULT_CONFIG = {
|
|
4
|
+
:base => Dir.pwd,
|
|
5
|
+
:preloads => []
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
def initialize(attrs = nil)
|
|
9
|
+
attrs ||= DEFAULT_CONFIG.dup
|
|
10
|
+
|
|
11
|
+
@base = attrs[:base]
|
|
12
|
+
@preloads = attrs[:preloads] || []
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
def resolve(mods)
|
|
16
|
+
@modules = []
|
|
17
|
+
@codes = []
|
|
18
|
+
|
|
19
|
+
if mods.is_a?(String)
|
|
20
|
+
mods = [mods]
|
|
21
|
+
end
|
|
22
|
+
mods.each do |mod|
|
|
23
|
+
resolve_mod(mod)
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
def resolve_mod(mod)
|
|
28
|
+
return if @preloads.include?(mod) || @modules.include?(mod)
|
|
29
|
+
|
|
30
|
+
mod = parse_mod(mod)
|
|
31
|
+
path = File.join(@base, "#{mod}.js")
|
|
32
|
+
code = File.open(path).read
|
|
33
|
+
|
|
34
|
+
unless code =~ /^define\((['"])[^'"]+\1/
|
|
35
|
+
code = polish(mod, code)
|
|
36
|
+
# fio = File.open(path, 'w')
|
|
37
|
+
# fio.write(code)
|
|
38
|
+
end
|
|
39
|
+
@codes.unshift(code)
|
|
40
|
+
@modules.unshift(mod)
|
|
41
|
+
|
|
42
|
+
deps = parse_deps_from_define(code)
|
|
43
|
+
deps.each do |dep|
|
|
44
|
+
dep = expand_path(mod, dep)
|
|
45
|
+
resolve_mod(dep)
|
|
46
|
+
end
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
def append(mod, code)
|
|
50
|
+
@modules << mod
|
|
51
|
+
@codes << polish(mod, code)
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
def bundle
|
|
55
|
+
@preloads.each do |file|
|
|
56
|
+
code = File.open(File.join(@base, "#{file}.js")).read
|
|
57
|
+
@codes.unshift(code)
|
|
58
|
+
end
|
|
59
|
+
@codes.join("\n")
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
# mark the module id
|
|
63
|
+
# parse and set the module dependencies if not present
|
|
64
|
+
def polish(mod, code = nil)
|
|
65
|
+
mod = parse_mod(mod)
|
|
66
|
+
|
|
67
|
+
return polish_code(mod, code) unless code.nil? || code == ''
|
|
68
|
+
|
|
69
|
+
path = File.join(@base, "#{mod}.js")
|
|
70
|
+
code = File.open(path).read
|
|
71
|
+
|
|
72
|
+
unless code =~ /^define\((['"])[^'"]+\1/
|
|
73
|
+
code = polish_code(mod, code)
|
|
74
|
+
fio = File.open(path, 'w')
|
|
75
|
+
fio.write(code)
|
|
76
|
+
fio.close
|
|
77
|
+
end
|
|
78
|
+
|
|
79
|
+
code
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
def polish_code(mod, code)
|
|
83
|
+
mod = parse_mod(mod)
|
|
84
|
+
|
|
85
|
+
if code =~ /^define\(function/
|
|
86
|
+
deps = parse_deps(code)
|
|
87
|
+
deps -= @preloads
|
|
88
|
+
deps_str = deps.length > 0 ? "['#{deps.join("', '")}']" : '[]'
|
|
89
|
+
|
|
90
|
+
code.sub!(/^(define\()/, "\\1'#{mod}', #{deps_str}, ")
|
|
91
|
+
elsif code =~ /^define\([\[\{]/
|
|
92
|
+
code.sub!(/^(define\()/, "\\1'#{mod}', ")
|
|
93
|
+
end
|
|
94
|
+
|
|
95
|
+
code
|
|
96
|
+
end
|
|
97
|
+
|
|
98
|
+
def parse_mod(mod)
|
|
99
|
+
start = 0
|
|
100
|
+
fini = mod.rindex('.js') || mod.length
|
|
101
|
+
|
|
102
|
+
mod.slice(start, fini - start)
|
|
103
|
+
end
|
|
104
|
+
|
|
105
|
+
def expand_path(mod, dep)
|
|
106
|
+
context = mod.include?('/') ? mod.slice(0, mod.rindex('/')) : ''
|
|
107
|
+
dep_bare = dep.slice(dep.index('/') || 0, dep.length)
|
|
108
|
+
ret = ''
|
|
109
|
+
|
|
110
|
+
if dep.starts_with?('./')
|
|
111
|
+
ret = context + dep_bare
|
|
112
|
+
elsif dep.starts_with?('../')
|
|
113
|
+
ret = context.slice(0, context.rindex('/')) + dep_bare
|
|
114
|
+
else
|
|
115
|
+
ret = dep
|
|
116
|
+
end
|
|
117
|
+
|
|
118
|
+
ret
|
|
119
|
+
end
|
|
120
|
+
|
|
121
|
+
def parse_deps_from_define(code)
|
|
122
|
+
pattern = /^define\((['"])[^'"]+\1,\s*(\[[^\]]+\])/
|
|
123
|
+
match = pattern.match(code)
|
|
124
|
+
deps = []
|
|
125
|
+
|
|
126
|
+
if match
|
|
127
|
+
deps = match[2]
|
|
128
|
+
deps = JSON.parse(deps.gsub("'", '"'))
|
|
129
|
+
deps.delete_if do |d|
|
|
130
|
+
d.blank?
|
|
131
|
+
end
|
|
132
|
+
else
|
|
133
|
+
pattern = /^define\((['"])[^'"]+\1,\s*(['"])([^\1]+)\1\.split/
|
|
134
|
+
match = pattern.match(code)
|
|
135
|
+
if match
|
|
136
|
+
deps = match[3].split(/,\s*/)
|
|
137
|
+
end
|
|
138
|
+
end
|
|
139
|
+
|
|
140
|
+
deps
|
|
141
|
+
end
|
|
142
|
+
|
|
143
|
+
def parse_deps(code)
|
|
144
|
+
# Parse these `requires`:
|
|
145
|
+
# var a = require('a');
|
|
146
|
+
# someMethod(require('b'));
|
|
147
|
+
# require('c');
|
|
148
|
+
# ...
|
|
149
|
+
# Doesn't parse:
|
|
150
|
+
# someInstance.require(...);
|
|
151
|
+
pattern = /(?:^|[^.])\brequire\s*\(\s*(["'])([^"'\s\)]+)\1\s*\)/
|
|
152
|
+
code = sans_comments(code)
|
|
153
|
+
matches = code.scan(pattern)
|
|
154
|
+
|
|
155
|
+
matches.map! do |m|
|
|
156
|
+
m[1]
|
|
157
|
+
end
|
|
158
|
+
|
|
159
|
+
matches.uniq.compact
|
|
160
|
+
end
|
|
161
|
+
|
|
162
|
+
# http://lifesinger.github.com/lab/2011/remove-comments-safely/
|
|
163
|
+
def sans_comments(code)
|
|
164
|
+
code.gsub(/(?:^|\n|\r)\s*\/\*[\s\S]*?\*\/\s*(?:\r|\n|$)/, "\n").gsub(/(?:^|\n|\r)\s*\/\/.*(?:\r|\n|$)/, "\n")
|
|
165
|
+
end
|
|
166
|
+
end
|
metadata
ADDED
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
|
2
|
+
name: rill
|
|
3
|
+
version: !ruby/object:Gem::Version
|
|
4
|
+
version: 0.0.1
|
|
5
|
+
prerelease:
|
|
6
|
+
platform: ruby
|
|
7
|
+
authors:
|
|
8
|
+
- Jake Chen
|
|
9
|
+
autorequire:
|
|
10
|
+
bindir: bin
|
|
11
|
+
cert_chain: []
|
|
12
|
+
date: 2012-08-20 00:00:00.000000000Z
|
|
13
|
+
dependencies: []
|
|
14
|
+
description: A simple CMD module bundler
|
|
15
|
+
email: jakeplus@gmail.com
|
|
16
|
+
executables:
|
|
17
|
+
- rill
|
|
18
|
+
extensions: []
|
|
19
|
+
extra_rdoc_files: []
|
|
20
|
+
files:
|
|
21
|
+
- lib/rill.rb
|
|
22
|
+
- bin/rill
|
|
23
|
+
homepage: http://rubygems.org/gems/rill
|
|
24
|
+
licenses: []
|
|
25
|
+
post_install_message:
|
|
26
|
+
rdoc_options: []
|
|
27
|
+
require_paths:
|
|
28
|
+
- lib
|
|
29
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
|
30
|
+
none: false
|
|
31
|
+
requirements:
|
|
32
|
+
- - ! '>='
|
|
33
|
+
- !ruby/object:Gem::Version
|
|
34
|
+
version: '0'
|
|
35
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
36
|
+
none: false
|
|
37
|
+
requirements:
|
|
38
|
+
- - ! '>='
|
|
39
|
+
- !ruby/object:Gem::Version
|
|
40
|
+
version: '0'
|
|
41
|
+
requirements: []
|
|
42
|
+
rubyforge_project:
|
|
43
|
+
rubygems_version: 1.8.15
|
|
44
|
+
signing_key:
|
|
45
|
+
specification_version: 3
|
|
46
|
+
summary: SeaJS Bundler in Ruby
|
|
47
|
+
test_files: []
|