multigiri 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +12 -0
- data/CHANGELOG +2 -0
- data/Gemfile +9 -0
- data/LICENSE +20 -0
- data/README.textile +21 -0
- data/TODO.txt +0 -0
- data/deps.rip +5 -0
- data/examples/config.ru +50 -0
- data/lib/multigiri/.gitignore +0 -0
- data/lib/multigiri/email_obfuscator.rb +20 -0
- data/lib/multigiri/google_analytics.rb +53 -0
- data/lib/multigiri/html5.rb +46 -0
- data/lib/multigiri/version.rb +7 -0
- data/lib/multigiri.rb +43 -0
- data/multigiri.gemspec +43 -0
- data/multigiri.pre.gemspec +8 -0
- data/spec/multigiri/.gitignore +0 -0
- data/spec/multigiri_spec.rb +10 -0
- data/spec/spec.opts +5 -0
- data/spec/spec_helper.rb +7 -0
- data/tasks.rb +37 -0
- metadata +83 -0
data/.gitignore
ADDED
data/CHANGELOG
ADDED
data/Gemfile
ADDED
data/LICENSE
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
Copyright (c) 2010 Jakub Stastny aka Botanicus
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
4
|
+
a copy of this software and associated documentation files (the
|
5
|
+
"Software"), to deal in the Software without restriction, including
|
6
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
7
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
8
|
+
permit persons to whom the Software is furnished to do so, subject to
|
9
|
+
the following conditions:
|
10
|
+
|
11
|
+
The above copyright notice and this permission notice shall be
|
12
|
+
included in all copies or substantial portions of the Software.
|
13
|
+
|
14
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
15
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
16
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
17
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
18
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
19
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
20
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.textile
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
h1. About
|
2
|
+
|
3
|
+
h1. Usage
|
4
|
+
|
5
|
+
Take a look at an "example":http://github.com/botanicus/multigiri/blob/master/examples/config.ru. The point is:
|
6
|
+
|
7
|
+
<pre>
|
8
|
+
use Multigiri do
|
9
|
+
use HTML5::Forms
|
10
|
+
use HTML5::Hidden
|
11
|
+
use EmailObfuscator
|
12
|
+
use GoogleAnalytics, :my_tracking_code
|
13
|
+
end
|
14
|
+
</pre>
|
15
|
+
|
16
|
+
h1. Links
|
17
|
+
|
18
|
+
* "Source Code":http://github.com/botanicus/multigiri
|
19
|
+
* "Wiki":http://wiki.github.com/botanicus/multigiri
|
20
|
+
* "API Docs":http://rdoc.info/projects/botanicus/multigiri
|
21
|
+
* "Bug reporting":http://github.com/botanicus/multigiri/issues
|
data/TODO.txt
ADDED
File without changes
|
data/deps.rip
ADDED
data/examples/config.ru
ADDED
@@ -0,0 +1,50 @@
|
|
1
|
+
#!/usr/bin/env rackup -p 4000 -s thin
|
2
|
+
|
3
|
+
$:.unshift(::File.expand_path("../../lib", __FILE__))
|
4
|
+
|
5
|
+
require "multigiri"
|
6
|
+
require "multigiri/html5"
|
7
|
+
require "multigiri/email_obfuscator"
|
8
|
+
require "multigiri/google_analytics"
|
9
|
+
|
10
|
+
# Multigiri change the last element of the rack array from body to
|
11
|
+
# nokogiri, document so instead of [status, headers, body] you'll get
|
12
|
+
# [status, headers, document]. After the multigiri block everything
|
13
|
+
# will get to normal, so middlewares whichrun later won't be affected.
|
14
|
+
use Multigiri do
|
15
|
+
use HTML5::Forms
|
16
|
+
use HTML5::Hidden
|
17
|
+
use EmailObfuscator
|
18
|
+
use GoogleAnalytics, :my_tracking_code
|
19
|
+
end
|
20
|
+
|
21
|
+
# It's especially important to run these middlewares after multigiri,
|
22
|
+
# because in multigiri middleware you probably change the resulted HTML
|
23
|
+
use ContentType
|
24
|
+
use ContentLength
|
25
|
+
|
26
|
+
# We can't use the trick with __END__ as is used in sinatra, since Rack
|
27
|
+
# authors are stupid idiots and the content of the rackup file is eval-ed.
|
28
|
+
# This crappy design leads to more problems than just this one.
|
29
|
+
# template = ::File.read(__FILE__).split("__END__").last
|
30
|
+
|
31
|
+
template = ::File.read(__FILE__).match(/=begin template\n(.+)\n=end/m)[1]
|
32
|
+
|
33
|
+
run lambda { |env| [200, Hash.new, [template]] }
|
34
|
+
|
35
|
+
=begin template
|
36
|
+
<html>
|
37
|
+
<body>
|
38
|
+
<h1>Hello World!</h1>
|
39
|
+
<a href='joe@example.com'>mail</a>
|
40
|
+
<p hidden>test</p>
|
41
|
+
<p hidden style="color:red">test</p>
|
42
|
+
<form method="GET">
|
43
|
+
</form>
|
44
|
+
<form method="PUT">
|
45
|
+
</form>
|
46
|
+
<form method="DELETE">
|
47
|
+
</form>
|
48
|
+
</body>
|
49
|
+
</html>
|
50
|
+
=end
|
File without changes
|
@@ -0,0 +1,20 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
module Rack
|
4
|
+
class Multigiri
|
5
|
+
class EmailObfuscator
|
6
|
+
def initialize(app)
|
7
|
+
@app = app
|
8
|
+
end
|
9
|
+
|
10
|
+
def call(env)
|
11
|
+
status, headers, document = @app.call(env)
|
12
|
+
# document.css("a[href~='@']").each do |element|
|
13
|
+
document.css("a[href]").each do |element|
|
14
|
+
element[:href] = element[:href].sub("@", "@")
|
15
|
+
end
|
16
|
+
[status, headers, document]
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
@@ -0,0 +1,53 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
# Add Google Analytics tracking to your page
|
4
|
+
|
5
|
+
# @example
|
6
|
+
# use Multigiri do
|
7
|
+
# use GoogleAnalytics, :my_tracking_code if Rango.production?
|
8
|
+
# end
|
9
|
+
|
10
|
+
module Rack
|
11
|
+
class Multigiri
|
12
|
+
class GoogleAnalytics
|
13
|
+
attr_accessor :tracking_code
|
14
|
+
def initialize(app, tracking_code)
|
15
|
+
@app, @tracking_code = app, tracking_code
|
16
|
+
end
|
17
|
+
|
18
|
+
def call(env)
|
19
|
+
status, headers, document = @app.call(env)
|
20
|
+
body = document.xpath("/html/body")[0]
|
21
|
+
|
22
|
+
# include scripts to the page
|
23
|
+
script(body, protocol_recognition_script)
|
24
|
+
script(body, tracker_script)
|
25
|
+
|
26
|
+
[status, headers, document]
|
27
|
+
end
|
28
|
+
|
29
|
+
protected
|
30
|
+
def script(body, content)
|
31
|
+
script = Nokogiri::XML::Node.new(:script, body.document)
|
32
|
+
script.inner_html = content
|
33
|
+
body.add_child(script)
|
34
|
+
end
|
35
|
+
|
36
|
+
def protocol_recognition_script
|
37
|
+
<<-EOF
|
38
|
+
var gaJsHost = (("https:" == document.location.protocol) ? "https://ssl." : "http://www.");
|
39
|
+
document.write(unescape("%3Cscript src='" + gaJsHost + "google-analytics.com/ga.js' type='text/javascript'%3E%3C/script%3E"));
|
40
|
+
EOF
|
41
|
+
end
|
42
|
+
|
43
|
+
def tracker_script
|
44
|
+
<<-EOF
|
45
|
+
try {
|
46
|
+
var pageTracker = _gat._getTracker("#{self.tracking_code}");
|
47
|
+
pageTracker._trackPageview();
|
48
|
+
} catch(err) {}
|
49
|
+
EOF
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
@@ -0,0 +1,46 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
module Rack
|
4
|
+
class Multigiri
|
5
|
+
module HTML5
|
6
|
+
class Forms
|
7
|
+
def initialize(app)
|
8
|
+
@app = app
|
9
|
+
end
|
10
|
+
|
11
|
+
def call(env)
|
12
|
+
status, headers, document = @app.call(env)
|
13
|
+
nodes = document.css("form[method=PUT]") + document.css("form[method=DELETE]")
|
14
|
+
nodes.each do |form|
|
15
|
+
input = Nokogiri::XML::Node.new("input", document)
|
16
|
+
input[:type] = "hidden"
|
17
|
+
input[:name] = "_method"
|
18
|
+
input[:value] = form[:method]
|
19
|
+
form[:method] = "POST"
|
20
|
+
form.add_child(input)
|
21
|
+
end
|
22
|
+
[status, headers, document]
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
class Hidden
|
27
|
+
def initialize(app)
|
28
|
+
@app = app
|
29
|
+
end
|
30
|
+
|
31
|
+
def call(env)
|
32
|
+
status, headers, document = @app.call(env)
|
33
|
+
document.css("[hidden]").each do |element|
|
34
|
+
element.remove_attribute("hidden")
|
35
|
+
if element[:style]
|
36
|
+
element[:style] += "; display: none"
|
37
|
+
else
|
38
|
+
element[:style] = "display:none"
|
39
|
+
end
|
40
|
+
end
|
41
|
+
[status, headers, document]
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
data/lib/multigiri.rb
ADDED
@@ -0,0 +1,43 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
# use Multigiri do
|
4
|
+
# use GoogleAnalytics, :my_tracking_code
|
5
|
+
# use EmailObfuscator
|
6
|
+
# use HTML5::Forms
|
7
|
+
# use HTML5::Hidden
|
8
|
+
# end
|
9
|
+
|
10
|
+
require "nokogiri"
|
11
|
+
|
12
|
+
# TODO: args for nokogiri, export format, indentation etc
|
13
|
+
module Rack
|
14
|
+
class Multigiri
|
15
|
+
def initialize(app, &block)
|
16
|
+
@app, @block = app, block
|
17
|
+
end
|
18
|
+
|
19
|
+
def call(env)
|
20
|
+
# convert to a Nokogiri document
|
21
|
+
status, headers, chunks = @app.call(env)
|
22
|
+
# the only what we know about body is that it has to respond to #each
|
23
|
+
body = String.new
|
24
|
+
chunks.each { |chunk| body += chunk }
|
25
|
+
document = Nokogiri::HTML(body) # before
|
26
|
+
@stack = lambda { |env| [status, headers, document] }
|
27
|
+
|
28
|
+
# get middlewares
|
29
|
+
self.instance_eval(&@block) if @block
|
30
|
+
|
31
|
+
# convert back to a [String]
|
32
|
+
status, headers, document = @stack.call(env)
|
33
|
+
body = document.to_html(indentation: 2) # TODO
|
34
|
+
headers["Content-Length"] = body.length.to_s
|
35
|
+
[status, headers, [body]]
|
36
|
+
end
|
37
|
+
|
38
|
+
# GoogleAnalytics.new(Other.new(self), tracking_code)
|
39
|
+
def use(klass, *args, &block)
|
40
|
+
@stack = klass.new(@stack, *args, &block)
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
data/multigiri.gemspec
ADDED
@@ -0,0 +1,43 @@
|
|
1
|
+
#!/usr/bin/env gem build
|
2
|
+
# encoding: utf-8
|
3
|
+
|
4
|
+
# Run ./multigiri.gemspec or gem build multigiri.gemspec
|
5
|
+
# NOTE: we can't use require_relative because when we run gem build, it use eval for executing this file
|
6
|
+
require File.join(File.dirname(__FILE__), "lib", "multigiri", "version")
|
7
|
+
require "base64"
|
8
|
+
|
9
|
+
Gem::Specification.new do |s|
|
10
|
+
s.name = "multigiri"
|
11
|
+
s.version = Rack::Multigiri::VERSION
|
12
|
+
s.authors = ["Jakub Stastny aka Botanicus"]
|
13
|
+
s.homepage = "http://github.com/botanicus/multigiri"
|
14
|
+
s.summary = "" # TODO: summary
|
15
|
+
s.description = "" # TODO: long description
|
16
|
+
s.cert_chain = nil
|
17
|
+
s.email = Base64.decode64("c3Rhc3RueUAxMDFpZGVhcy5jeg==\n")
|
18
|
+
s.has_rdoc = true
|
19
|
+
|
20
|
+
# files
|
21
|
+
s.files = `git ls-files`.split("\n")
|
22
|
+
|
23
|
+
s.executables = Dir["bin/*"].map(&File.method(:basename))
|
24
|
+
s.default_executable = "multigiri"
|
25
|
+
s.require_paths = ["lib"]
|
26
|
+
|
27
|
+
# Ruby version
|
28
|
+
s.required_ruby_version = ::Gem::Requirement.new(">= 1.9")
|
29
|
+
|
30
|
+
# runtime dependencies
|
31
|
+
s.add_dependency "nokogiri"
|
32
|
+
|
33
|
+
begin
|
34
|
+
require "changelog"
|
35
|
+
rescue LoadError
|
36
|
+
warn "You have to have changelog gem installed for post install message"
|
37
|
+
else
|
38
|
+
s.post_install_message = CHANGELOG.new.version_changes
|
39
|
+
end
|
40
|
+
|
41
|
+
# RubyForge
|
42
|
+
s.rubyforge_project = "multigiri"
|
43
|
+
end
|
@@ -0,0 +1,8 @@
|
|
1
|
+
#!/usr/bin/env gem build
|
2
|
+
# encoding: utf-8
|
3
|
+
|
4
|
+
# You might think this is a terrible mess and guess what, you're
|
5
|
+
# right mate! However say thanks to authors of RubyGems, not me.
|
6
|
+
eval(File.read("multigiri.gemspec")).tap do |specification|
|
7
|
+
specification.version = "#{specification.version}.pre"
|
8
|
+
end
|
File without changes
|
data/spec/spec.opts
ADDED
data/spec/spec_helper.rb
ADDED
data/tasks.rb
ADDED
@@ -0,0 +1,37 @@
|
|
1
|
+
#!./script/nake
|
2
|
+
# encoding: utf-8
|
3
|
+
|
4
|
+
begin
|
5
|
+
require_relative "gems/environment.rb"
|
6
|
+
rescue LoadError
|
7
|
+
abort "You have to install bundler and run gem bundle first!"
|
8
|
+
end
|
9
|
+
|
10
|
+
ENV["PATH"] = "script:#{ENV["PATH"]}"
|
11
|
+
|
12
|
+
require "nake/tasks/gem"
|
13
|
+
require "nake/tasks/spec"
|
14
|
+
require "nake/tasks/release"
|
15
|
+
|
16
|
+
require_relative "lib/multigiri/version"
|
17
|
+
|
18
|
+
begin
|
19
|
+
load "code-cleaner.nake"
|
20
|
+
Nake::Task["hooks:whitespace:install"].tap do |task|
|
21
|
+
task.config[:path] = "script"
|
22
|
+
task.config[:encoding] = "utf-8"
|
23
|
+
task.config[:whitelist] = '(bin/[^/]+|.+\.(rb|rake|nake|thor|task))$'
|
24
|
+
end
|
25
|
+
rescue LoadError
|
26
|
+
warn "If you want to contribute to Multigiri, please install code-cleaner and then run ./tasks.rb hooks:whitespace:install to get Git pre-commit hook for removing trailing whitespace."
|
27
|
+
end
|
28
|
+
|
29
|
+
# Setup encoding, so all the operations
|
30
|
+
# with strings from another files will work
|
31
|
+
Encoding.default_internal = "utf-8"
|
32
|
+
Encoding.default_external = "utf-8"
|
33
|
+
|
34
|
+
Task[:build].config[:gemspec] = "multigiri.gemspec"
|
35
|
+
Task[:prerelease].config[:gemspec] = "multigiri.pre.gemspec"
|
36
|
+
Task[:release].config[:name] = "multigiri"
|
37
|
+
Task[:release].config[:version] = Multigiri::VERSION
|
metadata
ADDED
@@ -0,0 +1,83 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: multigiri
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Jakub Stastny aka Botanicus
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain:
|
11
|
+
date: 2010-02-03 00:00:00 +00:00
|
12
|
+
default_executable: multigiri
|
13
|
+
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
15
|
+
name: nokogiri
|
16
|
+
type: :runtime
|
17
|
+
version_requirement:
|
18
|
+
version_requirements: !ruby/object:Gem::Requirement
|
19
|
+
requirements:
|
20
|
+
- - ">="
|
21
|
+
- !ruby/object:Gem::Version
|
22
|
+
version: "0"
|
23
|
+
version:
|
24
|
+
description: ""
|
25
|
+
email: stastny@101ideas.cz
|
26
|
+
executables: []
|
27
|
+
|
28
|
+
extensions: []
|
29
|
+
|
30
|
+
extra_rdoc_files: []
|
31
|
+
|
32
|
+
files:
|
33
|
+
- .gitignore
|
34
|
+
- CHANGELOG
|
35
|
+
- Gemfile
|
36
|
+
- LICENSE
|
37
|
+
- README.textile
|
38
|
+
- TODO.txt
|
39
|
+
- deps.rip
|
40
|
+
- examples/config.ru
|
41
|
+
- lib/multigiri.rb
|
42
|
+
- lib/multigiri/.gitignore
|
43
|
+
- lib/multigiri/email_obfuscator.rb
|
44
|
+
- lib/multigiri/google_analytics.rb
|
45
|
+
- lib/multigiri/html5.rb
|
46
|
+
- lib/multigiri/version.rb
|
47
|
+
- multigiri.gemspec
|
48
|
+
- multigiri.pre.gemspec
|
49
|
+
- spec/multigiri/.gitignore
|
50
|
+
- spec/multigiri_spec.rb
|
51
|
+
- spec/spec.opts
|
52
|
+
- spec/spec_helper.rb
|
53
|
+
- tasks.rb
|
54
|
+
has_rdoc: true
|
55
|
+
homepage: http://github.com/botanicus/multigiri
|
56
|
+
licenses: []
|
57
|
+
|
58
|
+
post_install_message: "[\e[32mVersion 0.0.1\e[0m] Initial import\n"
|
59
|
+
rdoc_options: []
|
60
|
+
|
61
|
+
require_paths:
|
62
|
+
- lib
|
63
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
64
|
+
requirements:
|
65
|
+
- - ">="
|
66
|
+
- !ruby/object:Gem::Version
|
67
|
+
version: "1.9"
|
68
|
+
version:
|
69
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
70
|
+
requirements:
|
71
|
+
- - ">="
|
72
|
+
- !ruby/object:Gem::Version
|
73
|
+
version: "0"
|
74
|
+
version:
|
75
|
+
requirements: []
|
76
|
+
|
77
|
+
rubyforge_project: multigiri
|
78
|
+
rubygems_version: 1.3.5
|
79
|
+
signing_key:
|
80
|
+
specification_version: 3
|
81
|
+
summary: ""
|
82
|
+
test_files: []
|
83
|
+
|