Skip to content

Commit

Permalink
Add exclude: param to relativize_paths filter
Browse files Browse the repository at this point in the history
  • Loading branch information
denisdefreyne committed Jun 9, 2018
1 parent b41b1f5 commit bfbb4df
Show file tree
Hide file tree
Showing 2 changed files with 159 additions and 17 deletions.
43 changes: 32 additions & 11 deletions nanoc/lib/nanoc/filters/relativize_paths.rb
Expand Up @@ -41,7 +41,7 @@ def run(content, params = {})
# Filter
case params[:type]
when :css
relativize_css(content)
relativize_css(content, params)
when :html, :html5, :xml, :xhtml
relativize_html_like(content, params)
else
Expand All @@ -53,15 +53,36 @@ def run(content, params = {})

protected

def relativize_css(content)
def relativize_css(content, params)
# FIXME: parse CSS the proper way using csspool or something
content.gsub(/url\((['"]?)(\/(?:[^\/].*?)?)\1\)/) do
quote = Regexp.last_match[1]
path = Regexp.last_match[2]
'url(' + quote + relative_path_to(path) + quote + ')'

if exclude?(path, params)
Regexp.last_match[0]
else
'url(' + quote + relative_path_to(path) + quote + ')'
end
end
end

def excludes(params)
raw = [params.fetch(:exclude, [])].flatten
raw.map do |exclusion|
case exclusion
when Regexp
exclusion
when String
/\A#{exclusion}(\z|\/)/
end
end
end

def exclude?(path, params)
excludes(params).any? { |ex| path.match?(ex) }
end

def relativize_html_like(content, params)
selectors = params.fetch(:select, SELECTORS)
namespaces = params.fetch(:namespaces, {})
Expand All @@ -71,7 +92,7 @@ def relativize_html_like(content, params)
parser = parser_for(type)
content = fix_content(content, type)

nokogiri_process(content, selectors, namespaces, parser, type, nokogiri_save_options)
nokogiri_process(content, selectors, namespaces, parser, type, nokogiri_save_options, params)
end

def parser_for(type)
Expand Down Expand Up @@ -104,7 +125,7 @@ def fix_content(content, type)
end
end

def nokogiri_process(content, selectors, namespaces, klass, type, nokogiri_save_options = nil)
def nokogiri_process(content, selectors, namespaces, klass, type, nokogiri_save_options, params)
# Ensure that all prefixes are strings
namespaces = namespaces.reduce({}) { |new, (prefix, uri)| new.merge(prefix.to_s => uri) }

Expand All @@ -114,8 +135,8 @@ def nokogiri_process(content, selectors, namespaces, klass, type, nokogiri_save_
selector = selectors.map { |sel| "descendant-or-self::#{sel}" }.join('|')
doc.xpath(selector, namespaces).each do |node|
if node.name == 'comment'
nokogiri_process_comment(node, doc, selectors, namespaces, klass, type)
elsif path_is_relativizable?(node.content)
nokogiri_process_comment(node, doc, selectors, namespaces, klass, type, params)
elsif path_is_relativizable?(node.content, params)
node.content = relative_path_to(node.content)
end
end
Expand All @@ -139,20 +160,20 @@ def revert_gcse_search_workaround(content)
content.gsub(GCSE_SEARCH_WORKAROUND, 'gcse:search')
end

def nokogiri_process_comment(node, doc, selectors, namespaces, klass, type)
def nokogiri_process_comment(node, doc, selectors, namespaces, klass, type, params)
content = node.content.dup.sub(%r{^(\s*\[.+?\]>\s*)(.+?)(\s*<!\[endif\])}m) do |_m|
beginning = Regexp.last_match[1]
body = Regexp.last_match[2]
ending = Regexp.last_match[3]

beginning + nokogiri_process(body, selectors, namespaces, klass, type) + ending
beginning + nokogiri_process(body, selectors, namespaces, klass, type, nil, params) + ending
end

node.replace(Nokogiri::XML::Comment.new(doc, content))
end

def path_is_relativizable?(path)
path.start_with?('/')
def path_is_relativizable?(path, params)
path.start_with?('/') && !exclude?(path, params)
end
end
end
133 changes: 127 additions & 6 deletions nanoc/spec/nanoc/filters/relativize_paths_spec.rb
Expand Up @@ -21,7 +21,7 @@
subject { filter.setup_and_run(content, params) }

let(:content) do
'<a href="/foo">Foo</a>'
'<a href="/foo/bar">Foo</a>'
end

let(:params) do
Expand All @@ -30,26 +30,147 @@

context 'HTML' do
let(:params) { { type: :html } }
it { is_expected.to eq('<a href="../foo">Foo</a>') }
it { is_expected.to eq('<a href="../foo/bar">Foo</a>') }

context 'full component excluded' do
let(:params) { { type: :html, exclude: '/foo' } }
it { is_expected.to eq('<a href="/foo/bar">Foo</a>') }
end

context 'full component excluded as list' do
let(:params) { { type: :html, exclude: ['/foo'] } }
it { is_expected.to eq('<a href="/foo/bar">Foo</a>') }
end

context 'partial component excluded' do
let(:params) { { type: :html, exclude: ['/fo'] } }
it { is_expected.to eq('<a href="../foo/bar">Foo</a>') }
end

context 'non-root component excluded' do
let(:params) { { type: :html, exclude: ['/bar'] } }
it { is_expected.to eq('<a href="../foo/bar">Foo</a>') }
end

context 'excluded with regexp' do
let(:params) { { type: :html, exclude: /ar/ } }
it { is_expected.to eq('<a href="/foo/bar">Foo</a>') }
end

context 'excluded with regexp list' do
let(:params) { { type: :html, exclude: [/ar/] } }
it { is_expected.to eq('<a href="/foo/bar">Foo</a>') }
end
end

context 'HTML5' do
let(:params) { { type: :html5 } }
it { is_expected.to eq('<a href="../foo">Foo</a>') }
it { is_expected.to eq('<a href="../foo/bar">Foo</a>') }

context 'full component excluded' do
let(:params) { { type: :html5, exclude: '/foo' } }
it { is_expected.to eq('<a href="/foo/bar">Foo</a>') }
end

context 'full component excluded as list' do
let(:params) { { type: :html5, exclude: ['/foo'] } }
it { is_expected.to eq('<a href="/foo/bar">Foo</a>') }
end

context 'partial component excluded' do
let(:params) { { type: :html5, exclude: ['/fo'] } }
it { is_expected.to eq('<a href="../foo/bar">Foo</a>') }
end

context 'non-root component excluded' do
let(:params) { { type: :html5, exclude: ['/bar'] } }
it { is_expected.to eq('<a href="../foo/bar">Foo</a>') }
end

context 'excluded with regexp' do
let(:params) { { type: :html5, exclude: /ar/ } }
it { is_expected.to eq('<a href="/foo/bar">Foo</a>') }
end

context 'excluded with regexp list' do
let(:params) { { type: :html5, exclude: [/ar/] } }
it { is_expected.to eq('<a href="/foo/bar">Foo</a>') }
end
end

context 'XHTML' do
let(:params) { { type: :xhtml } }
it { is_expected.to eq('<a href="../foo">Foo</a>') }
it { is_expected.to eq('<a href="../foo/bar">Foo</a>') }

context 'full component excluded' do
let(:params) { { type: :xhtml, exclude: '/foo' } }
it { is_expected.to eq('<a href="/foo/bar">Foo</a>') }
end

context 'full component excluded as list' do
let(:params) { { type: :xhtml, exclude: ['/foo'] } }
it { is_expected.to eq('<a href="/foo/bar">Foo</a>') }
end

context 'partial component excluded' do
let(:params) { { type: :xhtml, exclude: ['/fo'] } }
it { is_expected.to eq('<a href="../foo/bar">Foo</a>') }
end

context 'non-root component excluded' do
let(:params) { { type: :xhtml, exclude: ['/bar'] } }
it { is_expected.to eq('<a href="../foo/bar">Foo</a>') }
end

context 'excluded with regexp' do
let(:params) { { type: :xhtml, exclude: /ar/ } }
it { is_expected.to eq('<a href="/foo/bar">Foo</a>') }
end

context 'excluded with regexp list' do
let(:params) { { type: :xhtml, exclude: [/ar/] } }
it { is_expected.to eq('<a href="/foo/bar">Foo</a>') }
end
end

context 'CSS' do
let(:params) { { type: :css } }

let(:content) do
'.oink { background: url(/foo.png) }'
'.oink { background: url(/foo/bar.png) }'
end

it { is_expected.to eq('.oink { background: url(../foo.png) }') }
it { is_expected.to eq('.oink { background: url(../foo/bar.png) }') }

context 'full component excluded' do
let(:params) { { type: :css, exclude: '/foo' } }
it { is_expected.to eq('.oink { background: url(/foo/bar.png) }') }
end

context 'full component excluded as list' do
let(:params) { { type: :css, exclude: ['/foo'] } }
it { is_expected.to eq('.oink { background: url(/foo/bar.png) }') }
end

context 'partial component excluded' do
let(:params) { { type: :css, exclude: ['/fo'] } }
it { is_expected.to eq('.oink { background: url(../foo/bar.png) }') }
end

context 'non-root component excluded' do
let(:params) { { type: :css, exclude: ['/bar'] } }
it { is_expected.to eq('.oink { background: url(../foo/bar.png) }') }
end

context 'excluded with regexp' do
let(:params) { { type: :css, exclude: /ar/ } }
it { is_expected.to eq('.oink { background: url(/foo/bar.png) }') }
end

context 'excluded with regexp list' do
let(:params) { { type: :css, exclude: [/ar/] } }
it { is_expected.to eq('.oink { background: url(/foo/bar.png) }') }
end
end
end
end

0 comments on commit bfbb4df

Please sign in to comment.