marlene 0.1.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/.gitignore ADDED
@@ -0,0 +1,5 @@
1
+ bin/bm.pl
2
+ test*.js
3
+ TODO.markdown
4
+ *.bookmarklet
5
+ pkg
data/README.markdown ADDED
@@ -0,0 +1,17 @@
1
+ Marlene - A bookmarklet builder
2
+ ===============================
3
+
4
+ Marlene is inspired by John Grubers Perl based [JavaScript Bookmarklet Builder](http://daringfireball.net/2007/03/javascript_bookmarklet_builder).
5
+
6
+
7
+
8
+ Specs
9
+ -----
10
+
11
+ run specs with
12
+
13
+ spec spec/marlene_spec.rb --format specdoc
14
+
15
+ or
16
+
17
+ autospec
data/Rakefile ADDED
@@ -0,0 +1,19 @@
1
+ require File.dirname(__FILE__) + "/lib/marlene.rb"
2
+
3
+ begin
4
+ require 'jeweler'
5
+ Jeweler::Tasks.new do |gemspec|
6
+ gemspec.name = "marlene"
7
+ gemspec.version = Marlene::VERSION
8
+ gemspec.summary = "Bookmarklet Generator from a local or remote JavaScript file"
9
+ gemspec.description = "Marlene generates bookmarklet files or bookmarklet-pages from existing local javascript files or from remote javascript files represented by a URL."
10
+ gemspec.email = "thomduerr@gmail.com"
11
+ gemspec.homepage = "http://github.com/thomd/marlene/"
12
+ gemspec.authors = ["Thomas Duerr"]
13
+ gemspec.add_dependency "yui-compressor", ">= 0.9.1"
14
+ gemspec.add_dependency "mustache", ">= 0.11.2"
15
+ end
16
+ Jeweler::GemcutterTasks.new
17
+ rescue LoadError
18
+ puts "Jeweler not available. Install it with: gem install jeweler"
19
+ end
data/bin/bm.pl ADDED
@@ -0,0 +1,33 @@
1
+ #!/usr/bin/env perl
2
+ #
3
+ # http://daringfireball.net/2007/03/javascript_bookmarklet_builder
4
+
5
+ use strict;
6
+ use warnings;
7
+ use URI::Escape qw(uri_escape_utf8);
8
+ use open IO => ":utf8", # UTF8 by default
9
+ ":std"; # Apply to STDIN/STDOUT/STDERR
10
+
11
+ my $src = do { local $/; <> };
12
+
13
+ # Zap the first line if there's already a bookmarklet comment:
14
+ $src =~ s{^// ?javascript:.+\n}{};
15
+ my $bookmarklet = $src;
16
+
17
+ for ($bookmarklet) {
18
+ s{^\s*//.+\n}{}gm; # Kill comments.
19
+ s{\t}{ }gm; # Tabs to spaces
20
+ s{[ ]{2,}}{ }gm; # Space runs to one space
21
+ s{^\s+}{}gm; # Kill line-leading whitespace
22
+ s{\s+$}{}gm; # Kill line-ending whitespace
23
+ s{\n}{}gm; # Kill newlines
24
+ }
25
+
26
+ # Escape single- and double-quotes, spaces, control chars, unicode:
27
+ $bookmarklet = "javascript:" .
28
+ uri_escape_utf8($bookmarklet, qq('" \x00-\x1f\x7f-\xff));
29
+
30
+ print "// $bookmarklet\n" . $src;
31
+
32
+ # Put bookmarklet on clipboard:
33
+ `/bin/echo -n '$bookmarklet' | /usr/bin/pbcopy`;
data/bin/marlene ADDED
@@ -0,0 +1,112 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'rubygems'
4
+ require 'trollop'
5
+ require 'uri'
6
+ require 'net/http'
7
+ require File.dirname(__FILE__) + '/../lib/marlene.rb'
8
+
9
+ opts = Trollop::options do
10
+ version "Marlene 0.1 (c) 2010 Thomas Duerr"
11
+ banner <<-EOS
12
+ Marlene builds code for bookmarklets from a local or from a remote hoted javascript file.
13
+
14
+ Usage:
15
+ marlene [options] <input>
16
+
17
+ where <input> is a file path or an URI to a javascript file.
18
+
19
+ [options] are:
20
+ EOS
21
+
22
+ opt :file, "write bookmarklet to file. Otherwise output goes to clipboard (OSX only) and STDOUT", :default => false
23
+ opt :include, "include bookmarklet code on top of input file as a comment", :default => false
24
+ # opt :jslint, "analyse javascript code via jslint before", :default => false, :short => "-l"
25
+ opt :publish, "build html page for bookmarklet and open it in a browser.", :default => false
26
+ end
27
+
28
+ Trollop::die "need at least a javascript file-path or a valid URI as input" if ARGV.empty?
29
+
30
+ input = ARGV.to_s
31
+
32
+ uri = URI.extract(input, 'http')[0]
33
+ if uri.nil? then
34
+
35
+ #
36
+ # ===== local javascript ==========
37
+ #
38
+
39
+ # stop if file does not exist
40
+ Trollop::die "#{input} must exist" unless File.exist?(input) if input
41
+
42
+ # read javascript file
43
+ local_file = File.read(input)
44
+
45
+ # build bookmarklet
46
+ bookmarklet = local_file.compress.to_bookmarklet
47
+
48
+ # include bookmarklet code as comment on top of input file
49
+ if opts[:include]
50
+
51
+ # remove first line if there's already a bookmarklet comment and
52
+ input.gsub!(/^\/\/ javascript:.+\n\n/, '')
53
+
54
+ File.open(input, "w") do |f|
55
+ f.puts "// #{bookmarklet}\n\n#{local_file}"
56
+ end
57
+ end
58
+
59
+ else
60
+
61
+ #
62
+ # ===== remote javascript ==========
63
+ #
64
+
65
+ # stop if URIs HTTP status is not 200
66
+ def remote_file_exists?(url)
67
+ url = URI.parse(url)
68
+ Net::HTTP.start(url.host, url.port) do |http|
69
+ return http.head(url.request_uri).code == "200"
70
+ end
71
+ end
72
+ Trollop::die "#{uri} must exist" unless remote_file_exists?(uri) if uri
73
+
74
+ # build bookmarklet loadscript
75
+ bookmarklet = uri.to_loader_script.compress.to_bookmarklet
76
+
77
+ end
78
+
79
+
80
+ #
81
+ # ===== output ==========
82
+ #
83
+ if opts[:file]
84
+
85
+ # write bookmarklet code to a file "filename.bookmarklet"
86
+ output = input.gsub(Regexp.new(File.extname(input)), ".bookmarklet")
87
+ File.open(output, "w").write(bookmarklet)
88
+ else
89
+
90
+ # copy bookmarklet code to clipboard (OSX only)
91
+ IO.popen('pbcopy', 'w').puts bookmarklet
92
+ end
93
+
94
+
95
+ # generate and open html page with bookmarklet-link in order to drag'n'drop bookmarklet up to bookmarks-bar
96
+ if opts[:publish]
97
+ begin
98
+ require 'bcat'
99
+ IO.popen('bcat', 'w').puts bookmarklet.to_bookmarklet_page
100
+ rescue LoadError => e
101
+ puts "Error: Publishing requires bcat gem: http://rtomayko.github.com/bcat/"
102
+ exit 1
103
+ end
104
+ end
105
+
106
+
107
+ # write to stdout
108
+ if !opts[:publish] && !opts[:file]
109
+ puts bookmarklet
110
+ end
111
+
112
+
data/lib/marlene.rb ADDED
@@ -0,0 +1,60 @@
1
+ require "uri"
2
+ require "yui/compressor"
3
+ require "mustache"
4
+
5
+
6
+ module Marlene
7
+
8
+ VERSION = "0.1.1"
9
+ ANCHOR_TEXTNODE = "bookmarklet"
10
+ PSEUDOCOL = "javascript:"
11
+ LOADER_SCRIPT = File.join(File.dirname(__FILE__), 'templates', 'loader.js')
12
+ BOOKMARKLET_PAGE = File.join(File.dirname(__FILE__), 'templates', 'page.html')
13
+
14
+ def yui_compressor
15
+ YUI::JavaScriptCompressor.new(:munge => true)
16
+ end
17
+
18
+ end
19
+
20
+
21
+ class String
22
+ include Marlene
23
+
24
+ # transform into bookmarklet
25
+ def to_bookmarklet
26
+ js = self.to_s
27
+ js.gsub!(/^ +/, '') # remove line-leading whitespace
28
+ js.gsub!(/ +$/, '') # remove line-ending whitespace
29
+ js.gsub!(/\t/, ' ') # replace tabs with spaces
30
+ js.gsub!(/ +/, ' ') # replace multiple spaces with a single space
31
+ js.gsub!(/^ *\/\/.+\n/, '') # remove comment lines starting with a double slash
32
+ js.gsub!(/\n/, '') # remove all newlines
33
+ js = URI.escape(js, %Q(''" )) # URI escape: single- and double-quotes, spaces
34
+ PSEUDOCOL + js # prefix with 'javascript:'
35
+ end
36
+
37
+ # use YUI compressor to minimize javascript code
38
+ def compress
39
+ yui_compressor.compress(self)
40
+ end
41
+
42
+ # insert into loader script a javascript URL
43
+ def to_loader_script
44
+ Mustache.template_file = LOADER_SCRIPT
45
+ loader = Mustache.new
46
+ loader[:script] = self
47
+ loader.render
48
+ end
49
+
50
+ # insert bookmarklet into html code for drag-drop bookmarklet up to linkbar
51
+ def to_bookmarklet_page
52
+ Mustache.template_file = BOOKMARKLET_PAGE
53
+ page = Mustache.new
54
+ page[:bookmarklet] = self
55
+ page[:anchor] = ANCHOR_TEXTNODE
56
+ page.render
57
+ end
58
+
59
+ end
60
+
@@ -0,0 +1,6 @@
1
+ (function(){
2
+ var script = document.createElement('script');
3
+ script.type = 'text/javascript';
4
+ script.src = '{{script}}?' + (new Date().getTime());
5
+ document.getElementsByTagName('body')[0].appendChild(script);
6
+ })()
@@ -0,0 +1,10 @@
1
+ <!DOCTYPE html>
2
+ <html>
3
+ <head>
4
+ <meta charset="utf-8" />
5
+ <title>{{anchor}}</title>
6
+ </head>
7
+ <body>
8
+ <a href="{{{bookmarklet}}}">{{anchor}}</a>
9
+ </body>
10
+ </html>
@@ -0,0 +1,105 @@
1
+ require "rubygems"
2
+ require "spec"
3
+ require File.dirname(__FILE__) + '/../lib/marlene.rb'
4
+
5
+ describe "Marlene bookmark generator" do
6
+
7
+ before(:all) do
8
+ @remote_url = "http://example.com/this/is/a/remote/javascript.js"
9
+ end
10
+
11
+ it "should transform a local javascript file to a bookmarklet" do
12
+ input = javascript_local
13
+ output = bookmarklet_local
14
+ input.to_bookmarklet.should == output
15
+ end
16
+
17
+ it "should transform and escape a local javascript file to a bookmarklet" do
18
+ input = javascript_local_unescaped
19
+ output = bookmarklet_local_escaped
20
+ input.to_bookmarklet.should == output
21
+ end
22
+
23
+ it "should transform an external javascript into a bookmarklet loaderscript" do
24
+ input = @remote_url
25
+ output = bookmarklet_remote
26
+ input.to_loader_script.to_bookmarklet.should == output
27
+ end
28
+
29
+ it "should compress javascript code with a javascript compressor" do
30
+ input = javascript_local
31
+ output = javascript_local_compressed
32
+ input.compress.should == output
33
+ end
34
+
35
+ it "should transform a local javascript file to a compressed bookmarklet" do
36
+ input = javascript_local
37
+ output = bookmarklet_local_compressed
38
+ input.compress.to_bookmarklet.should == output
39
+ end
40
+
41
+ it "should transform an external javascript into a compressed bookmarklet loaderscript" do
42
+ input = @remote_url
43
+ output = bookmarklet_remote_compressed
44
+ input.to_loader_script.compress.to_bookmarklet.should == output
45
+ end
46
+
47
+ it "should write a html page with a bookmarklet link" do
48
+ input = javascript_local_compressed
49
+ output = html_page_compressed_bookmarklet
50
+ input.compress.to_bookmarklet.to_bookmarklet_page.should == output
51
+ end
52
+
53
+ end
54
+
55
+ # fixtures
56
+
57
+ def javascript_local
58
+ "// a contains method for arrays
59
+ Array.prototype.contains = function(item){
60
+ return this.indexOf(item) > -1;
61
+ }
62
+
63
+ alert([1,2,3,4,5].contains(4));"
64
+ end
65
+
66
+ def javascript_local_unescaped
67
+ %Q{console.info(indentString + methodName, '-> ', result, "(", new Date - startTime, 'ms', ")");}
68
+ end
69
+
70
+ def javascript_local_compressed
71
+ "Array.prototype.contains=function(a){return this.indexOf(a)>-1};alert([1,2,3,4,5].contains(4));"
72
+ end
73
+
74
+ def bookmarklet_local
75
+ "javascript:Array.prototype.contains%20=%20function(item){return%20this.indexOf(item)%20>%20-1;}alert([1,2,3,4,5].contains(4));"
76
+ end
77
+
78
+ def bookmarklet_local_escaped
79
+ %Q{javascript:console.info(indentString%20+%20methodName,%20%27->%20%27,%20result,%20%22(%22,%20new%20Date%20-%20startTime,%20%27ms%27,%20%22)%22);}
80
+ end
81
+
82
+ def bookmarklet_local_compressed
83
+ "javascript:Array.prototype.contains=function(a){return%20this.indexOf(a)>-1};alert([1,2,3,4,5].contains(4));"
84
+ end
85
+
86
+ def bookmarklet_remote
87
+ "javascript:(function(){var%20script%20=%20document.createElement(%27script%27);script.type%20=%20%27text/javascript%27;script.src%20=%20%27http://example.com/this/is/a/remote/javascript.js?%27%20+%20(new%20Date().getTime());document.getElementsByTagName(%27body%27)[0].appendChild(script);})()"
88
+ end
89
+
90
+ def bookmarklet_remote_compressed
91
+ "javascript:(function(){var%20a=document.createElement(%22script%22);a.type=%22text/javascript%22;a.src=%22http://example.com/this/is/a/remote/javascript.js?%22+(new%20Date().getTime());document.getElementsByTagName(%22body%22)[0].appendChild(a)})();"
92
+ end
93
+
94
+ def html_page_compressed_bookmarklet
95
+ %Q(<!DOCTYPE html>
96
+ <html>
97
+ <head>
98
+ <meta charset="utf-8" />
99
+ <title>bookmarklet</title>
100
+ </head>
101
+ <body>
102
+ <a href="javascript:Array.prototype.contains=function(b){return%20this.indexOf(b)>-1};alert([1,2,3,4,5].contains(4));">bookmarklet</a>
103
+ </body>
104
+ </html>)
105
+ end
metadata ADDED
@@ -0,0 +1,107 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: marlene
3
+ version: !ruby/object:Gem::Version
4
+ hash: 25
5
+ prerelease: false
6
+ segments:
7
+ - 0
8
+ - 1
9
+ - 1
10
+ version: 0.1.1
11
+ platform: ruby
12
+ authors:
13
+ - Thomas Duerr
14
+ autorequire:
15
+ bindir: bin
16
+ cert_chain: []
17
+
18
+ date: 2010-07-09 00:00:00 +02:00
19
+ default_executable:
20
+ dependencies:
21
+ - !ruby/object:Gem::Dependency
22
+ name: yui-compressor
23
+ prerelease: false
24
+ requirement: &id001 !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - ">="
28
+ - !ruby/object:Gem::Version
29
+ hash: 57
30
+ segments:
31
+ - 0
32
+ - 9
33
+ - 1
34
+ version: 0.9.1
35
+ type: :runtime
36
+ version_requirements: *id001
37
+ - !ruby/object:Gem::Dependency
38
+ name: mustache
39
+ prerelease: false
40
+ requirement: &id002 !ruby/object:Gem::Requirement
41
+ none: false
42
+ requirements:
43
+ - - ">="
44
+ - !ruby/object:Gem::Version
45
+ hash: 55
46
+ segments:
47
+ - 0
48
+ - 11
49
+ - 2
50
+ version: 0.11.2
51
+ type: :runtime
52
+ version_requirements: *id002
53
+ description: Marlene generates bookmarklet files or bookmarklet-pages from existing local javascript files or from remote javascript files represented by a URL.
54
+ email: thomduerr@gmail.com
55
+ executables:
56
+ - bm.pl
57
+ - marlene
58
+ extensions: []
59
+
60
+ extra_rdoc_files:
61
+ - README.markdown
62
+ files:
63
+ - .gitignore
64
+ - README.markdown
65
+ - Rakefile
66
+ - bin/marlene
67
+ - lib/marlene.rb
68
+ - lib/templates/loader.js
69
+ - lib/templates/page.html
70
+ - spec/marlene_spec.rb
71
+ - bin/bm.pl
72
+ has_rdoc: true
73
+ homepage: http://github.com/thomd/marlene/
74
+ licenses: []
75
+
76
+ post_install_message:
77
+ rdoc_options:
78
+ - --charset=UTF-8
79
+ require_paths:
80
+ - lib
81
+ required_ruby_version: !ruby/object:Gem::Requirement
82
+ none: false
83
+ requirements:
84
+ - - ">="
85
+ - !ruby/object:Gem::Version
86
+ hash: 3
87
+ segments:
88
+ - 0
89
+ version: "0"
90
+ required_rubygems_version: !ruby/object:Gem::Requirement
91
+ none: false
92
+ requirements:
93
+ - - ">="
94
+ - !ruby/object:Gem::Version
95
+ hash: 3
96
+ segments:
97
+ - 0
98
+ version: "0"
99
+ requirements: []
100
+
101
+ rubyforge_project:
102
+ rubygems_version: 1.3.7
103
+ signing_key:
104
+ specification_version: 3
105
+ summary: Bookmarklet Generator from a local or remote JavaScript file
106
+ test_files:
107
+ - spec/marlene_spec.rb