rack-xsl 0.2.6

Sign up to get free protection for your applications and to get access to all the features.
data/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ The MIT License
2
+
3
+ Copyright (c) 2009 Savonix Corporation
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in
13
+ all copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
+ THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,52 @@
1
+ # Rack XSL README
2
+
3
+ Summary
4
+ -------
5
+
6
+ A rack middleware for transforming XML with XSL.
7
+
8
+ Configuration
9
+ -------------
10
+
11
+ This is how I would like it to work, but its not there yet:
12
+
13
+ <pre class="sh_ruby">
14
+ require 'xml/xslt'
15
+ require 'rack/xsl'
16
+
17
+ myxslfile = File.dirname(__FILE__) + '/app/views/layouts/xsl/html_main.xsl'
18
+ use Rack::XSLView,
19
+ :myxsl => XML::XSLT.new(),
20
+ :noxsl => ['/raw/', '/s/js/', '/s/css/', '/s/img/'],
21
+ :passenv => ['PATH_INFO', 'RACK_MOUNT_PATH', 'RACK_ENV'],
22
+ :xslfile => File.open(myxslfile) {|f| f.read },
23
+ :excludehtml => false,
24
+ :reload => true,
25
+ :tidy => { :doctype => 'omit',
26
+ :numeric_entities => 1,
27
+ :drop_proprietary_attributes => 1,
28
+ :preserve_entities => 0,
29
+ :input_encoding => 'utf8',
30
+ :char_encoding => 'utf8',
31
+ :output_encoding => 'utf8',
32
+ :error_file => '/tmp/tidyerr.txt',
33
+ :force_output => 1,
34
+ :alt_text => '',
35
+ :tidy_mark => 0,
36
+ :logical_emphasis => 1,
37
+ }
38
+
39
+ </pre>
40
+
41
+
42
+ Resources
43
+ ---------
44
+
45
+ * <http://www.docunext.com/wiki/Rack-XSLView>
46
+ * <http://github.com/docunext/Rack-XSLView>
47
+
48
+
49
+ Thanks
50
+ ------
51
+
52
+ The rack-rewrite gem was very helpful in figuring out how to write rack middleware with lots of options.
data/Rakefile ADDED
@@ -0,0 +1,61 @@
1
+ require 'rubygems'
2
+ require 'rake'
3
+
4
+ begin
5
+ require 'jeweler'
6
+ Jeweler::Tasks.new do |gem|
7
+ gem.name = "rack-xsl"
8
+ gem.summary = %Q{XSL rack middleware.}
9
+ gem.description = %Q{Rack middleware for transforming XML with XSL.}
10
+ gem.email = 'albert.lash@docunext.com'
11
+ gem.homepage = 'http://www.docunext.com/wiki/Rack-XSLView'
12
+ gem.authors = ['Albert Lash']
13
+ gem.rubyforge_project = ''
14
+ gem.add_development_dependency 'shoulda'
15
+ # gem is a Gem::Specification... see http://www.rubygems.org/read/chapter/20 for additional settings
16
+ end
17
+ Jeweler::GemcutterTasks.new
18
+ Jeweler::RubyforgeTasks.new do |rubyforge|
19
+ rubyforge.doc_task = 'rdoc'
20
+ end
21
+ rescue LoadError
22
+ puts 'Jeweler (or a dependency) not available. Install it with: sudo gem install jeweler'
23
+ end
24
+
25
+
26
+ require 'rake/testtask'
27
+ Rake::TestTask.new(:test) do |test|
28
+ test.libs << 'lib' << 'test'
29
+ test.pattern = 'test/**/*_test.rb'
30
+ test.verbose = true
31
+ end
32
+
33
+ begin
34
+ require 'rcov/rcovtask'
35
+ Rcov::RcovTask.new do |test|
36
+ test.libs << 'test'
37
+ test.pattern = 'test/**/*_test.rb'
38
+ test.verbose = true
39
+ end
40
+ rescue LoadError
41
+ task :rcov do
42
+ abort "RCov is not available. In order to run rcov, you must: sudo gem install spicycode-rcov"
43
+ end
44
+ end
45
+
46
+ task :default => :test
47
+ task :spec => :test
48
+
49
+ require 'rake/rdoctask'
50
+ Rake::RDocTask.new do |rdoc|
51
+ if File.exist?('VERSION')
52
+ version = File.read('VERSION')
53
+ else
54
+ version = ""
55
+ end
56
+
57
+ rdoc.rdoc_dir = 'rdoc'
58
+ rdoc.title = "rack-xslview #{version}"
59
+ rdoc.rdoc_files.include('README*')
60
+ rdoc.rdoc_files.include('lib/**/*.rb')
61
+ end
data/VERSION ADDED
@@ -0,0 +1 @@
1
+ 0.2.6
@@ -0,0 +1,32 @@
1
+ <!--
2
+ Program: 1bb02b59
3
+ Component: output.xhtml10.xsl
4
+ Copyright: Savonix Corporation
5
+ Author: Albert L. Lash, IV
6
+ License: Apache License, Version 2.0
7
+
8
+ Copyright 2009 Savonix Corporation
9
+
10
+ Licensed under the Apache License, Version 2.0 (the "License");
11
+ you may not use this file except in compliance with the License.
12
+ You may obtain a copy of the License at
13
+
14
+ http://www.apache.org/licenses/LICENSE-2.0
15
+
16
+ Unless required by applicable law or agreed to in writing, software
17
+ distributed under the License is distributed on an "AS IS" BASIS,
18
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
19
+ See the License for the specific language governing permissions and
20
+ limitations under the License.
21
+ -->
22
+ <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
23
+ xmlns="http://www.w3.org/1999/xhtml">
24
+
25
+ <xsl:import href="http://github.com/docunext/1bb02b59/raw/master/standard.html.xsl"/>
26
+
27
+
28
+ <xsl:output method="xml" encoding="UTF-8" omit-xml-declaration="no"
29
+ doctype-system="http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"
30
+ doctype-public="-//W3C//DTD XHTML 1.0 Transitional//EN" indent="yes"/>
31
+
32
+ </xsl:stylesheet>
data/lib/rack/xsl.rb ADDED
@@ -0,0 +1,126 @@
1
+ # Copyright 2010 Savonix Corporation
2
+ # Author Albert L. Lash, IV
3
+ # License MIT
4
+ require 'rexml/document'
5
+ module Rack
6
+ class XSL
7
+
8
+ class RackXSLError < StandardError ; end
9
+
10
+ def initialize(app, options)
11
+ @app = app
12
+ @options = {:myxsl => nil}.merge(options)
13
+ if @options[:myxsl].nil?
14
+ require 'rexml/document'
15
+ @xslt = XML::XSLT.new()
16
+ @xslt.xsl = REXML::Document.new '<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns="http://www.w3.org/1999/xhtml"><xsl:import href="http://github.com/docunext/1bb02b59/raw/master/standard.html.xsl"/><xsl:output method="xml" encoding="UTF-8" omit-xml-declaration="no" doctype-system="http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd" doctype-public="-//W3C//DTD XHTML 1.0 Transitional//EN" indent="yes"/></xsl:stylesheet>'
17
+ else
18
+ @xslt = @options[:myxsl]
19
+ end
20
+ end
21
+
22
+ def call(env)
23
+ # No matter what, @app will be called
24
+ status, headers, body = @app.call(env)
25
+ original_response = Array[status, headers, body]
26
+ exluded_status = Array[204, 301, 302, 304]
27
+ return original_response if exluded_status.include?(status) || body.nil?
28
+
29
+ return original_response unless headers["Content-Type"].to_s.match(/(ht|x)ml/)
30
+
31
+ # If setup includes paths to exclude from xslt processing, check them
32
+ checknoxsl(env) if @options[:noxsl]
33
+
34
+ # Obtain entire request body, ensuring sure it can be processed
35
+ myxml = getResponse(body)
36
+
37
+ # One more check for an empty respone
38
+ return original_response if myxml.empty?
39
+
40
+ # Should XSL file be reloaded?
41
+ if @options[:reload] == true
42
+ @xslt = XML::XSLT.new()
43
+ @xslt.xsl = REXML::Document.new @options[:xslfile]
44
+ end
45
+
46
+ unless @options[:tidy].nil?
47
+ input_xml = myxml.include?('http://www.w3.org/1999/xhtml') ? 0 : 1
48
+ output = myxml.include?('http://www.w3.org/1999/xhtml') ? 'output_xhtml' : 'output_xml'
49
+ @options[:tidy][:input_xml] = input_xml
50
+ @options[:tidy][output.to_sym] = 1
51
+ nuxml = ''
52
+ nuxml = TidyFFI::Tidy.new(myxml, @options[:tidy]).clean
53
+ myxml = nuxml
54
+ end
55
+ @xslt.xml = myxml
56
+
57
+ # If setup includes env vars to pass through as params, do so
58
+ unless @options[:passenv].nil?
59
+ @myhash = {}
60
+ @options[:passenv].each { |envkey|
61
+ # Does env var exist?
62
+ @myhash[envkey] = "#{env[envkey]}" if env[envkey]
63
+ }
64
+ @xslt.parameters = @myhash unless @myhash.empty?
65
+ end
66
+
67
+ # Perform the transformation
68
+ newbody = Array.[](@xslt.serve)
69
+
70
+ # If we've made it this far, we can alter the headers
71
+ headers.delete('Content-Length')
72
+ headers['Content-Length'] = newbody[0].length.to_s
73
+
74
+ # Content type override?
75
+ unless @options[:content_type].nil?
76
+ headers["Content-Type"] = @options[:content_type]
77
+ end
78
+
79
+ [status, headers, newbody]
80
+
81
+ rescue RackXSLError
82
+ # TODO Log: "Rack XSL not processed" if env['RACK_ENV'] == 'development'
83
+ original_response
84
+ end
85
+
86
+ private
87
+ def checknoxsl(env)
88
+ @options[:noxsl].each { |path|
89
+ raise RackXSLError if env["PATH_INFO"].index(path)
90
+ }
91
+ end
92
+ def getResponse(body)
93
+ newbody = []
94
+ body.each { |part|
95
+ # Only check the first chunk to ensure 1) its not HTML and 2) its XML
96
+ checkForXml(part) if newbody.empty?
97
+ newbody << part.to_s
98
+ }
99
+ return newbody.join('')
100
+ end
101
+ def checkForXml(x)
102
+ # Abort processing if content cannot be processed by libxslt
103
+ #puts "test for xml"
104
+ #puts x[0]
105
+ if RUBY_VERSION > '1.9'
106
+ raise RackXSLError unless x[0] == '<'
107
+ else
108
+ raise RackXSLError unless x[0] == 60
109
+ end
110
+ #puts "end xml test"
111
+ if @options[:excludehtml] == true
112
+ raise RackXSLError if x.include? '<html'
113
+ end
114
+ end
115
+
116
+ def choosesheet(env)
117
+ # Not used yet, this may be used to match stylesheets with paths
118
+ @options[:xslhash].each_key { |path|
119
+ if env["PATH_INFO"].index(path)
120
+ return @options[:xslhash][path]
121
+ end
122
+ }
123
+ return false
124
+ end
125
+ end
126
+ end
@@ -0,0 +1,52 @@
1
+ require 'test_helper'
2
+ require 'xml/xslt'
3
+
4
+ class RackXslviewTest < Test::Unit::TestCase
5
+
6
+ def call_args(overrides={})
7
+ {'REQUEST_URI' => '/rlksdjfkj', 'PATH_INFO' => '/notsure', 'RACK_MOUNT_PATH' => '/something'}.merge(overrides)
8
+
9
+ end
10
+
11
+
12
+ def self.should_not_halt
13
+ should "not halt the rack chain" do
14
+ @app.expects(:call).once
15
+ @rack.call(call_args)
16
+ end
17
+ end
18
+
19
+ def self.should_be_a_rack_response
20
+ should 'be a rack a response' do
21
+ ret = @rack.call(call_args)
22
+ assert ret.is_a?(Array), 'return value is not a valid rack response'
23
+ assert_equal 3, ret.size, 'should have 3 arguments'
24
+ end
25
+ end
26
+
27
+
28
+ context 'Given an app' do
29
+ setup do
30
+ @app = Class.new { def call(app); true; end }.new
31
+ end
32
+
33
+ context 'Still learning how to write these tests...' do
34
+ setup {
35
+ omitpaths = [/^\/raw/, '/s/js/', '/s/css/']
36
+ passenv = ['PATH_INFO', 'RACK_MOUNT_PATH']
37
+ @rack = Rack::XSL.new(@app, :noxsl => omitpaths, :passenv => passenv)
38
+ }
39
+ should_be_a_rack_response
40
+ should_not_halt
41
+ end
42
+ context 'Trying out the xslhash' do
43
+ setup {
44
+ omitpaths = [/^\/raw/, '/s/js/', '/s/css/']
45
+ xslhash = { "/path/alskjddf" => "test.xsl", /specific\.xml$/ => 'different.xsl' }
46
+ xslhash.default("/path/to/output.xhtml10.xsl")
47
+ @rack = Rack::XSL.new(@app, :noxsl => omitpaths, :xslhash => xslhash)
48
+ }
49
+ should_be_a_rack_response
50
+ end
51
+ end
52
+ end
@@ -0,0 +1,13 @@
1
+ require 'rubygems'
2
+ require 'test/unit'
3
+ require 'shoulda'
4
+ require 'mocha'
5
+
6
+ $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
7
+ $LOAD_PATH.unshift(File.dirname(__FILE__))
8
+ require 'rack/xsl'
9
+
10
+ class Test::Unit::TestCase
11
+ end
12
+
13
+ TEST_ROOT = File.dirname(__FILE__)
@@ -0,0 +1 @@
1
+
metadata ADDED
@@ -0,0 +1,84 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: rack-xsl
3
+ version: !ruby/object:Gem::Version
4
+ prerelease: false
5
+ segments:
6
+ - 0
7
+ - 2
8
+ - 6
9
+ version: 0.2.6
10
+ platform: ruby
11
+ authors:
12
+ - Albert Lash
13
+ autorequire:
14
+ bindir: bin
15
+ cert_chain: []
16
+
17
+ date: 2011-01-01 00:00:00 -05:00
18
+ default_executable:
19
+ dependencies:
20
+ - !ruby/object:Gem::Dependency
21
+ name: shoulda
22
+ prerelease: false
23
+ requirement: &id001 !ruby/object:Gem::Requirement
24
+ requirements:
25
+ - - ">="
26
+ - !ruby/object:Gem::Version
27
+ segments:
28
+ - 0
29
+ version: "0"
30
+ type: :development
31
+ version_requirements: *id001
32
+ description: Rack middleware for transforming XML with XSL.
33
+ email: albert.lash@docunext.com
34
+ executables: []
35
+
36
+ extensions: []
37
+
38
+ extra_rdoc_files:
39
+ - LICENSE
40
+ - README.md
41
+ files:
42
+ - LICENSE
43
+ - README.md
44
+ - Rakefile
45
+ - VERSION
46
+ - lib/output.xhtml10.xsl
47
+ - lib/rack/xsl.rb
48
+ - test/rack-xslview_test.rb
49
+ - test/test_helper.rb
50
+ - test/test_install.rb
51
+ has_rdoc: true
52
+ homepage: http://www.docunext.com/wiki/Rack-XSLView
53
+ licenses: []
54
+
55
+ post_install_message:
56
+ rdoc_options: []
57
+
58
+ require_paths:
59
+ - lib
60
+ required_ruby_version: !ruby/object:Gem::Requirement
61
+ requirements:
62
+ - - ">="
63
+ - !ruby/object:Gem::Version
64
+ segments:
65
+ - 0
66
+ version: "0"
67
+ required_rubygems_version: !ruby/object:Gem::Requirement
68
+ requirements:
69
+ - - ">="
70
+ - !ruby/object:Gem::Version
71
+ segments:
72
+ - 0
73
+ version: "0"
74
+ requirements: []
75
+
76
+ rubyforge_project: ""
77
+ rubygems_version: 1.3.6
78
+ signing_key:
79
+ specification_version: 3
80
+ summary: XSL rack middleware.
81
+ test_files:
82
+ - test/rack-xslview_test.rb
83
+ - test/test_helper.rb
84
+ - test/test_install.rb