fast_jsmin 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
data/README.md ADDED
@@ -0,0 +1,15 @@
1
+ # fast_jsmin
2
+
3
+ This is a ruby -> c wrapper extension for Douglas Crockford's awesome jsmin.
4
+
5
+ ## Usage
6
+
7
+ require 'fast_jsmin'
8
+
9
+ jsmin = JSMin.new
10
+ puts jsmin.minimize(File.read("foo.js"))
11
+
12
+
13
+ ## Install
14
+
15
+ gem install fast_jsmin
data/extconf.rb ADDED
@@ -0,0 +1,5 @@
1
+ require 'mkmf'
2
+ create_makefile('fast_jsmin')
3
+ system('make clean')
4
+ system('make all')
5
+ # require 'test_jsmin'
data/fast_jsmin.c ADDED
@@ -0,0 +1,339 @@
1
+ /* jsmin.c
2
+ 2012-12-04
3
+
4
+ Copyright (c) 2002 Douglas Crockford (www.crockford.com)
5
+
6
+ Permission is hereby granted, free of charge, to any person obtaining a copy of
7
+ this software and associated documentation files (the "Software"), to deal in
8
+ the Software without restriction, including without limitation the rights to
9
+ use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
10
+ of the Software, and to permit persons to whom the Software is furnished to do
11
+ so, subject to the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be included in all
14
+ copies or substantial portions of the Software.
15
+
16
+ The Software shall be used for Good, not Evil.
17
+
18
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
21
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
24
+ SOFTWARE.
25
+ */
26
+
27
+ #include <stdlib.h>
28
+ #include <stdio.h>
29
+ #include "ruby.h"
30
+
31
+ static int theA;
32
+ static int theB;
33
+ static int theLookahead = EOF;
34
+ static int theX = EOF;
35
+ static int theY = EOF;
36
+
37
+ static const char *src;
38
+ static int src_len;
39
+ static char *dest;
40
+ static int srci, desti;
41
+
42
+ /* isAlphanum -- return true if the character is a letter, digit, underscore,
43
+ dollar sign, or non-ASCII character.
44
+ */
45
+
46
+ static int
47
+ isAlphanum(int c)
48
+ {
49
+ return ((c >= 'a' && c <= 'z') || (c >= '0' && c <= '9') ||
50
+ (c >= 'A' && c <= 'Z') || c == '_' || c == '$' || c == '\\' ||
51
+ c > 126);
52
+ }
53
+
54
+
55
+ /* get -- return the next character from stdin. Watch out for lookahead. If
56
+ the character is a control character, translate it to a space or
57
+ linefeed.
58
+ */
59
+
60
+ static int
61
+ get()
62
+ {
63
+ int c = theLookahead;
64
+ theLookahead = EOF;
65
+ if (c == EOF) {
66
+ if (srci < src_len) {
67
+ c = src[srci++];
68
+ } else {
69
+ c = EOF;
70
+ }
71
+ }
72
+ if (c >= ' ' || c == '\n' || c == EOF) {
73
+ return c;
74
+ }
75
+ if (c == '\r') {
76
+ return '\n';
77
+ }
78
+ return ' ';
79
+ }
80
+
81
+
82
+ /* peek -- get the next character without getting it.
83
+ */
84
+
85
+ static int
86
+ peek()
87
+ {
88
+ theLookahead = get();
89
+ return theLookahead;
90
+ }
91
+
92
+
93
+ /* next -- get the next character, excluding comments. peek() is used to see
94
+ if a '/' is followed by a '/' or '*'.
95
+ */
96
+
97
+ static int
98
+ next()
99
+ {
100
+ int c = get();
101
+ if (c == '/') {
102
+ switch (peek()) {
103
+ case '/':
104
+ for (;;) {
105
+ c = get();
106
+ if (c <= '\n') {
107
+ break;
108
+ }
109
+ }
110
+ break;
111
+ case '*':
112
+ get();
113
+ while (c != ' ') {
114
+ switch (get()) {
115
+ case '*':
116
+ if (peek() == '/') {
117
+ get();
118
+ c = ' ';
119
+ }
120
+ break;
121
+ case EOF:
122
+ rb_raise(rb_eException, "JSMIN Unterminated comment.");
123
+ }
124
+ }
125
+ break;
126
+ }
127
+ }
128
+ theY = theX;
129
+ theX = c;
130
+ return c;
131
+ }
132
+
133
+
134
+ static inline void put_to_dest(int c)
135
+ {
136
+ /* this should be impossible? */
137
+ if (desti <= src_len)
138
+ dest[desti++] = c;
139
+ else {
140
+ printf("desti: %d < src_len: %d\n", desti, src_len);
141
+ rb_raise(rb_eIndexError, "JSMIN target file is larger than source.");
142
+ }
143
+ }
144
+
145
+ /* action -- do something! What you do is determined by the argument:
146
+ 1 Output A. Copy B to A. Get the next B.
147
+ 2 Copy B to A. Get the next B. (Delete A).
148
+ 3 Get the next B. (Delete B).
149
+ action treats a string as a single character. Wow!
150
+ action recognizes a regular expression if it is preceded by ( or , or =.
151
+ */
152
+
153
+ static void
154
+ action(int d)
155
+ {
156
+ int p;
157
+ switch (d) {
158
+ case 1:
159
+ put_to_dest(theA);
160
+ if (
161
+ (theY == '\n' || theY == ' ') &&
162
+ (theA == '+' || theA == '-' || theA == '*' || theA == '/') &&
163
+ (theB == '+' || theB == '-' || theB == '*' || theB == '/')
164
+ ) {
165
+ put_to_dest(theY);
166
+ }
167
+ case 2:
168
+ theA = theB;
169
+ if (theA == '\'' || theA == '"' || theA == '`') {
170
+ for (;;) {
171
+ put_to_dest(theA);
172
+ theA = get();
173
+ if (theA == theB) {
174
+ break;
175
+ }
176
+ if (theA == '\\') {
177
+ put_to_dest(theA);
178
+ theA = get();
179
+ }
180
+ if (theA == EOF) {
181
+ rb_raise(rb_eException, "JSMIN unterminated string literal.");
182
+ }
183
+ }
184
+ }
185
+ case 3:
186
+ theB = next();
187
+ if (theB == '/' && (
188
+ theA == '(' || theA == ',' || theA == '=' || theA == ':' ||
189
+ theA == '[' || theA == '!' || theA == '&' || theA == '|' ||
190
+ theA == '?' || theA == '+' || theA == '-' || theA == '~' ||
191
+ theA == '*' || theA == '/' || theA == '\n'
192
+ )) {
193
+ put_to_dest(theA);
194
+ if (theA == '/' || theA == '*') {
195
+ put_to_dest(' ');
196
+ }
197
+ put_to_dest(theB);
198
+ for (;;) {
199
+ theA = get();
200
+ if (theA == '[') {
201
+ for (;;) {
202
+ put_to_dest(theA);
203
+ theA = get();
204
+ if (theA == ']') {
205
+ break;
206
+ }
207
+ if (theA == '\\') {
208
+ put_to_dest(theA);
209
+ theA = get();
210
+ }
211
+ if (theA == EOF) {
212
+ rb_raise(rb_eException, "JSMIN unterminated Regular Expression literal.");
213
+ }
214
+ }
215
+ } else if (theA == '/') {
216
+ switch (peek()) {
217
+ case '/':
218
+ case '*':
219
+ rb_raise(rb_eException, "JSMIN unterminated Regular Expression literal.");
220
+ }
221
+ break;
222
+ } else if (theA =='\\') {
223
+ put_to_dest(theA);
224
+ theA = get();
225
+ }
226
+ if (theA == EOF) {
227
+ rb_raise(rb_eException, "JSMIN unterminated Regular Expression literal.");
228
+ }
229
+ put_to_dest(theA);
230
+ }
231
+ theB = next();
232
+ }
233
+ }
234
+ }
235
+
236
+
237
+ /* jsmin -- Copy the input to the output, deleting the characters which are
238
+ insignificant to JavaScript. Comments will be removed. Tabs will be
239
+ replaced with spaces. Carriage returns will be replaced with linefeeds.
240
+ Most spaces and linefeeds will be removed.
241
+ */
242
+
243
+ static void
244
+ jsmin()
245
+ {
246
+ if (peek() == 0xEF) {
247
+ get();
248
+ get();
249
+ get();
250
+ }
251
+ theA = '\n';
252
+ action(3);
253
+ while (theA != EOF) {
254
+ switch (theA) {
255
+ case ' ':
256
+ action(isAlphanum(theB) ? 1 : 2);
257
+ break;
258
+ case '\n':
259
+ switch (theB) {
260
+ case '{':
261
+ case '[':
262
+ case '(':
263
+ case '+':
264
+ case '-':
265
+ case '!':
266
+ case '~':
267
+ action(1);
268
+ break;
269
+ case ' ':
270
+ action(3);
271
+ break;
272
+ default:
273
+ action(isAlphanum(theB) ? 1 : 2);
274
+ }
275
+ break;
276
+ default:
277
+ switch (theB) {
278
+ case ' ':
279
+ action(isAlphanum(theA) ? 1 : 3);
280
+ break;
281
+ case '\n':
282
+ switch (theA) {
283
+ case '}':
284
+ case ']':
285
+ case ')':
286
+ case '+':
287
+ case '-':
288
+ case '"':
289
+ case '\'':
290
+ case '`':
291
+ action(1);
292
+ break;
293
+ default:
294
+ action(isAlphanum(theA) ? 1 : 3);
295
+ }
296
+ break;
297
+ default:
298
+ action(1);
299
+ break;
300
+ }
301
+ }
302
+ }
303
+ }
304
+
305
+ static VALUE jsmin_initialize(VALUE self)
306
+ {
307
+ return self;
308
+ }
309
+
310
+ static VALUE jsmin_convert(VALUE self, VALUE str)
311
+ {
312
+ VALUE ret_str;
313
+
314
+ src = RSTRING_PTR(str);
315
+ src_len = RSTRING_LEN(str);
316
+
317
+ srci = desti = 0;
318
+ dest = malloc(src_len+1);
319
+ if (!dest)
320
+ rb_raise(rb_eNoMemError, "malloc failed in %s", __func__);
321
+
322
+ jsmin();
323
+
324
+ ret_str = rb_str_new(dest, desti);
325
+
326
+ free(dest);
327
+
328
+ return ret_str;
329
+ }
330
+
331
+ static VALUE cl;
332
+
333
+ void Init_fast_jsmin()
334
+ {
335
+ cl = rb_define_class("JSMin", rb_cObject);
336
+ rb_define_method(cl, "initialize", jsmin_initialize, 0);
337
+ rb_define_method(cl, "convert", jsmin_convert, 1);
338
+ rb_define_method(cl, "minimize", jsmin_convert, 1);
339
+ }
@@ -0,0 +1,28 @@
1
+ Gem::Specification.new do |s|
2
+ s.name = 'fast_jsmin'
3
+ s.author = 'Adit Bhargava'
4
+ s.email = 'adit@adit.io'
5
+ s.version = '0.0.1'
6
+ s.date = '2013-02-15'
7
+ s.homepage = 'https://github.com/egonSchiele/fast_jsmin'
8
+ s.summary = 'JSMin wrapper for Ruby'
9
+ s.has_rdoc = true
10
+ s.require_path = 'fast_jsmin'
11
+ s.description = <<END
12
+ This is a ruby -> C wrapper extension for Douglas Crockford's awesome jsmin.
13
+ END
14
+ s.files = %w(
15
+ README.md
16
+ extconf.rb
17
+ fast_jsmin.c
18
+ fast_jsmin.gemspec
19
+ spec/test_jsmin.rb
20
+ )
21
+ s.files.reject! { |fn| fn.include? ".svn" }
22
+ s.files.reject! { |fn| fn.include? ".git" }
23
+ s.required_ruby_version = '>= 1.8.6'
24
+ s.extensions = [
25
+ 'extconf.rb'
26
+ ]
27
+ end
28
+
@@ -0,0 +1,9 @@
1
+ require 'rubygems'
2
+ require "fast_jsmin"
3
+
4
+ describe 'jsmin' do
5
+ it 'minifies javascript' do
6
+ jsmin = JSMin.new
7
+ jsmin.minimize("var test = 1;").should_not fail
8
+ end
9
+ end
metadata ADDED
@@ -0,0 +1,60 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: fast_jsmin
3
+ version: !ruby/object:Gem::Version
4
+ prerelease:
5
+ version: 0.0.1
6
+ platform: ruby
7
+ authors:
8
+ - Adit Bhargava
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+
13
+ date: 2013-02-15 00:00:00 Z
14
+ dependencies: []
15
+
16
+ description: |
17
+ This is a ruby -> C wrapper extension for Douglas Crockford's awesome jsmin.
18
+
19
+ email: adit@adit.io
20
+ executables: []
21
+
22
+ extensions:
23
+ - extconf.rb
24
+ extra_rdoc_files: []
25
+
26
+ files:
27
+ - README.md
28
+ - extconf.rb
29
+ - fast_jsmin.c
30
+ - fast_jsmin.gemspec
31
+ - spec/test_jsmin.rb
32
+ homepage: https://github.com/egonSchiele/fast_jsmin
33
+ licenses: []
34
+
35
+ post_install_message:
36
+ rdoc_options: []
37
+
38
+ require_paths:
39
+ - fast_jsmin
40
+ required_ruby_version: !ruby/object:Gem::Requirement
41
+ none: false
42
+ requirements:
43
+ - - ">="
44
+ - !ruby/object:Gem::Version
45
+ version: 1.8.6
46
+ required_rubygems_version: !ruby/object:Gem::Requirement
47
+ none: false
48
+ requirements:
49
+ - - ">="
50
+ - !ruby/object:Gem::Version
51
+ version: "0"
52
+ requirements: []
53
+
54
+ rubyforge_project:
55
+ rubygems_version: 1.8.11
56
+ signing_key:
57
+ specification_version: 3
58
+ summary: JSMin wrapper for Ruby
59
+ test_files: []
60
+