rack-xsl 0.2.6

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/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