Created
December 7, 2014 01:21
-
-
Save julik/4155e885ca53d4b7aec6 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
require 'uri' | |
module Julik | |
module AbsolutizeHelper | |
def canonicalize_hyperlinks(htmlcontent, root, host = nil, prot = nil) | |
htmlcontent.gsub(/(<(img|a)\b[^>]*(src|href)=)(["'])(.*?)\4/) do | |
md = $~ | |
prefix = (host && prot) ? (prot + host) : '' | |
prefix.gsub!(/\/$/, '') | |
begin | |
url = URI.parse CGI.unescapeHTML(md[5]) | |
prefix = '' if (md[5].include?(prefix) && prefix.length > 0) | |
if url.relative? && url.path !~ /^\// | |
absolutized = File.expand_path(File.join(root, md[5], md[4])) | |
# Clean the trailing slash but leave the quote | |
absolutized.gsub!(/(\/)(["'])$/) { $2 } | |
md[1] + md[4] + prefix + absolutized | |
else | |
md[1] + md[4] + prefix + md[5] + md[4] | |
end | |
rescue URI::InvalidURIError | |
md[0] | |
end | |
end | |
end | |
def canonicalize_hyperlinks_in_context(html) | |
host = request.host | |
proto = request.protocol | |
# honor substandard port | |
host += ":#{request.port}" unless request.port == '80' | |
canonicalize_hyperlinks(html, '/', request.host, request.protocol) | |
end | |
def markdown_with_canonic_links(text) | |
canonicalize_hyperlinks_in_context(markdown(text)) | |
end | |
def textilize_with_canonic_links(text) | |
canonicalize_hyperlinks_in_context(textilize(text)) | |
end | |
end | |
end | |
require 'rubygems' | |
require 'action_pack' | |
require 'action_controller' | |
require 'action_controller/test_process' | |
require File.dirname(__FILE__) + '/../init' | |
# Re-raise errors caught by the controller. | |
class SomeController < ActionController::Base | |
def absolute_action_with_markdown | |
render :inline => "<%= markdown_with_canonic_links('And [a link](../some/stuff)') %>" | |
end | |
def absolute_action_with_textile | |
render :inline => "<%= textilize_with_canonic_links('And \"a link\":../some/stuff') %>" | |
end | |
def rescue_action(e) | |
raise e | |
end | |
end | |
ActionController::Routing::Routes.draw do |map| | |
map.connect ':controller/:action/:id' | |
end | |
class AbsolutizerTest < Test::Unit::TestCase | |
include Julik::AbsolutizeHelper | |
def setup | |
@request = ActionController::TestRequest.new | |
@response = ActionController::TestResponse.new | |
@controller = SomeController.new | |
end | |
def test_basisc | |
stuff = "Here is <a href='http://site.net/link'>stuffed</a> and \ | |
<a href='/some/interesting url to check out'>some ad uri</a> and \ | |
<a href='/some_link'>link</a> and <a href='../things'>another</a>" | |
result = "Here is <a href='http://site.net/link'>stuffed</a> and \ | |
<a href='/some/interesting url to check out'>some ad uri</a> and \ | |
<a href='http://site.net/some_link'>link</a> and <a href='http://site.net/stuff/bla/things'>another</a>" | |
assert_equal result, canonicalize_hyperlinks(stuff, '/stuff/bla/badaboum', 'site.net', 'http://') | |
assert_equal result, canonicalize_hyperlinks(stuff, '/stuff/bla/badaboum/', 'site.net', 'http://') | |
stuff = 'And <a href="/this/link">is a root link</a> as we know' | |
result_without_host = 'And <a href="/this/link">is a root link</a> as we know' | |
result_with_host = 'And <a href="https://host.com:3030/this/link">is a root link</a> as we know' | |
assert_equal result_without_host, canonicalize_hyperlinks(stuff, '/') | |
assert_equal result_with_host, canonicalize_hyperlinks(stuff, '/', 'host.com:3030', 'https://') | |
expectation = '<p>And <a href="http://test.host/some/stuff">a link</a></p>' | |
get :absolute_action_with_markdown | |
assert_equal expectation, @response.body | |
get :absolute_action_with_textile | |
assert_equal expectation, @response.body | |
end | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment