Skip to content

Commit

Permalink
resolves asciidoctor#3929 treat uri:classloader: as absolute path pre…
Browse files Browse the repository at this point in the history
…fix when running on JRuby
  • Loading branch information
mojavelinux committed Apr 29, 2023
1 parent e29edee commit cd8ccb3
Show file tree
Hide file tree
Showing 9 changed files with 102 additions and 4 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.adoc
Expand Up @@ -79,6 +79,7 @@ Bug Fixes::
* Adjust font size of term in horizontal dlist to match font size of term in regular dlist
* Implicitly attach nested list that starts with block attribute lines to dlist entry (#4268)
* Don't swallow square brackets when processing escaped URL macro
* Treat `uri:classloader:` as an absolute path prefix when running on JRuby (#3929)

== 2.0.18 (2022-10-15) - @mojavelinux

Expand Down
10 changes: 8 additions & 2 deletions lib/asciidoctor/helpers.rb
Expand Up @@ -121,8 +121,14 @@ def prepare_source_string data, trim_end = true
# str - the String to check
#
# returns true if the String is a URI, false if it is not
def uriish? str
(str.include? ':') && (UriSniffRx.match? str)
if ::RUBY_ENGINE == 'jruby'
def uriish? str
(str.include? ':') && !(str.start_with? 'uri:classloader:') && (UriSniffRx.match? str)
end
else
def uriish? str
(str.include? ':') && (UriSniffRx.match? str)
end
end

# Internal: Encode a URI component String for safe inclusion in a URI.
Expand Down
13 changes: 11 additions & 2 deletions lib/asciidoctor/path_resolver.rb
Expand Up @@ -110,6 +110,7 @@ class PathResolver
SLASH = '/'
BACKSLASH = '\\'
DOUBLE_SLASH = '//'
URI_CLASSLOADER = 'uri:classloader:'
WindowsRootRx = %r(^(?:[a-zA-Z]:)?[\\/])

attr_accessor :file_separator
Expand Down Expand Up @@ -149,8 +150,9 @@ def absolute_path? path
# Public: Check if the specified path is an absolute root path (or, in the
# browser environment, an absolute URI as well)
#
# This operation considers both posix paths and Windows paths. If the JavaScript IO
# module is xmlhttprequest, this operation also considers absolute URIs.
# This operation considers both POSIX and Windows paths. If the JavaScript IO module
# is xmlhttprequest, this operation also considers absolute URIs. If running on JRuby,
# this operation also considers classloader URIs (starts with uri:classloader:).
#
# Unix absolute paths and UNC paths start with slash. Windows roots can
# start with a drive letter. When the IO module is xmlhttprequest (Opal
Expand All @@ -165,6 +167,10 @@ def absolute_path? path
def root? path
(absolute_path? path) || (path.start_with? 'file://', 'http://', 'https://')
end
elsif ::RUBY_ENGINE == 'jruby'
def root? path
(absolute_path? path) || (path.start_with? URI_CLASSLOADER)
end
else
alias root? absolute_path?
end
Expand Down Expand Up @@ -300,6 +306,9 @@ def partition_path path, web = nil
# ex. /sample/path
elsif posix_path.start_with? SLASH
root = SLASH
# ex. uri:classloader:sample/path (or uri:classloader:/sample/path)
elsif posix_path.start_with? URI_CLASSLOADER
root = posix_path.slice 0, URI_CLASSLOADER.length
# ex. C:/sample/path (or file:///sample/path in browser environment)
else
root = posix_path.slice 0, (posix_path.index SLASH) + 1
Expand Down
36 changes: 36 additions & 0 deletions test/api_test.rb
Expand Up @@ -1348,6 +1348,22 @@ def for name
assert_include 'color: green', styles
end

test '.only should embed custom stylesheet read from classloader URI', if: jruby? do
require fixture_path 'assets.jar'
input = <<~'EOS'
= Document Title
text
EOS

output = Asciidoctor.convert input, safe: :unsafe, standalone: true, attributes: { 'stylesdir' => 'uri:classloader:/styles-in-jar', 'stylesheet' => 'custom.css' }
stylenode = xmlnodes_at_css 'html:root > head > style', output, 1
styles = stylenode.content
refute_nil styles
refute_empty styles.strip
assert_include 'color: green', styles
end

test 'should embed custom stylesheet in remote stylesdir if SafeMode is less than SECURE and allow-uri-read is set' do
input = <<~'EOS'
= Document Title
Expand Down Expand Up @@ -1438,6 +1454,26 @@ def for name
end
end

test 'should copy custom stylesheet to destination dir if copycss is a classloader URI', if: jruby? do
require fixture_path 'assets.jar'
begin
output_dir = fixture_path 'output'
sample_input_path = fixture_path 'sample.adoc'
sample_output_path = File.join output_dir, 'sample.html'
custom_stylesheet_src_path = 'uri:classloader:/styles-in-jar/custom.css'
custom_stylesheet_output_path = File.join output_dir, 'styles.css'
Asciidoctor.convert_file sample_input_path,
safe: :unsafe, to_dir: output_dir, mkdirs: true, attributes: { 'stylesheet' => 'styles.css', 'linkcss' => true, 'copycss' => custom_stylesheet_src_path }
assert_path_exists sample_output_path
assert_path_exists custom_stylesheet_output_path
output = File.read sample_output_path, mode: Asciidoctor::FILE_READ_MODE
assert_xpath '/html/head/link[@rel="stylesheet"][@href="./styles.css"]', output, 1
assert_xpath 'style', output, 0
ensure
FileUtils.rm_r output_dir, force: true, secure: true
end
end

test 'should convert source file and write result to adjacent file by default' do
sample_input_path = fixture_path 'sample.adoc'
sample_output_path = fixture_path 'sample.html'
Expand Down
15 changes: 15 additions & 0 deletions test/blocks_test.rb
Expand Up @@ -2894,6 +2894,21 @@ def names
assert_xpath '//img[@src="data:image/gif;base64,R0lGODlhAQABAIAAAAUEBAAAACwAAAAAAQABAAACAkQBADs="][@alt="Dot"]', output, 1
end

test 'embeds base64-encoded data uri for image in classloader when data-uri attribute is set', if: jruby? do
require fixture_path 'assets.jar'
input = <<~'EOS'
:data-uri:
:imagesdir: uri:classloader:/images-in-jar
image::dot.gif[Dot]
EOS

doc = document_from_string input, safe: Asciidoctor::SafeMode::UNSAFE, attributes: { 'docdir' => testdir }
assert_equal 'uri:classloader:/images-in-jar', doc.attributes['imagesdir']
output = doc.convert
assert_xpath '//img[@src="data:image/gif;base64,R0lGODlhAQABAIAAAAUEBAAAACwAAAAAAQABAAACAkQBADs="][@alt="Dot"]', output, 1
end

test 'embeds SVG image with image/svg+xml mimetype when file extension is .svg' do
input = <<~'EOS'
:imagesdir: fixtures
Expand Down
Binary file added test/fixtures/assets.jar
Binary file not shown.
10 changes: 10 additions & 0 deletions test/helpers_test.rb
Expand Up @@ -52,6 +52,16 @@
assert Asciidoctor::UriSniffRx !~ 'c:\\sample.adoc'
end

test 'uriish? should not detect a classloader path as a URI on JRuby' do
input = 'uri:classloader:/sample.png'
assert Asciidoctor::UriSniffRx =~ input
if jruby?
refute Asciidoctor::Helpers.uriish? input
else
assert Asciidoctor::Helpers.uriish? input
end
end

test 'UriSniffRx should not detect URI that does not start on first line' do
assert Asciidoctor::UriSniffRx !~ %(text\nhttps://example.org)
end
Expand Down
12 changes: 12 additions & 0 deletions test/paths_test.rb
Expand Up @@ -284,6 +284,18 @@ def setup
assert_equal '//server/docs/output.html', @resolver.system_path('//server/docs/output.html')
end

test 'resolves classloader path if start is classloader path and target is relative', if: jruby? do
assert_equal 'uri:classloader:images/sample.png', @resolver.system_path('sample.png', 'uri:classloader:images')
end

test 'resolves classloader path if start is root-relative classloader path and target is relative', if: jruby? do
assert_equal 'uri:classloader:/images/sample.png', @resolver.system_path('sample.png', 'uri:classloader:/images')
end

test 'preserves classloader path if start is absolute path and target is classloader path', if: jruby? do
assert_equal 'uri:classloader:/images/sample.png', @resolver.system_path('uri:classloader:/images/sample.png', '/home/doctor/docs')
end

test 'resolves relative target relative to current directory if start is empty' do
pwd = File.expand_path Dir.pwd
assert_equal "#{pwd}/images/tiger.png", @resolver.system_path('images/tiger.png', '')
Expand Down
9 changes: 9 additions & 0 deletions test/reader_test.rb
Expand Up @@ -740,6 +740,15 @@ class ReaderTest < Minitest::Test
assert_match(/<h1>人<\/h1>/, output)
end

test 'should include content from a file on the classloader', if: jruby? do
require fixture_path 'assets.jar'
input = 'include::uri:classloader:/includes-in-jar/include-file.adoc[]'
doc = document_from_string input, safe: :unsafe, standalone: false, base_dir: DIRNAME
output = doc.convert
assert_match(/included from a file/, output)
assert doc.catalog[:includes]['uri:classloader:/includes-in-jar/include-file']
end

test 'should not track include in catalog for non-AsciiDoc include files' do
input = <<~'EOS'
----
Expand Down

0 comments on commit cd8ccb3

Please sign in to comment.