Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP

Loading…

Allow to load CSS documents from <link> tags for an string HTML #131

Open
wants to merge 1 commit into from

4 participants

@rykov

Currently, tags do terrible things when using Premailer with inline HTML. In the code that I'm changing, it tries to do File.join(@html_file, ...) where @html_file is the HTML string. I think a better approach is to use @base_dir as the root for CSS files and make sure that our HTML is local. Otherwise, let the following remote fetching code retrieve the file.

Furthermore, I've added a :base_dir option to be able to specify the base_dir in the case where it cannot be inferred from the @html_file path (like inline HTML)

@rzschech

+1 on this. I'm using premailer-rails3 with an action_mailer.asset_host set which mean my css links are absolute uris. premailer-rails3 passes the html to premailer as a string which then hits this issue.

@rzschech rzschech referenced this pull request in fphilipe/premailer-rails
Open

Remove read stylesheets from HTML #48

@akzhan
Owner

Hello, is this PR actual for us? Today premailer supports file protocol for links.

@rykov

1+ year later, I'm having trouble understanding my issue description as well, but after some digging, I remembered that this change fixes asset lookup when using Premailer with :with_html_string option. I want this because I'm doing some template pre-processing before I run Premailer. Let me give an example of what I mean.

html_str = <<HTML
  <html><head>
    <link rel="stylesheet" href="http://mysite.com/css/style.css" /> 
 </head>... </html>
HTML

premailer = Premailer.new(html_str,
  :with_html_string => true,
  :base_url => 'http://mysite.com'
)

In this case, when Premailer tries to look up the location of the stylesheet with the following statement:

link_uri = File.join(File.dirname(@html_file), tag.attributes['href'].to_s.sub!(@base_url.to_s, ''))

@html_file is the actual HTML (html_str in the above example), so the link_uri does not yield a useful file path. And if you look at subsequent link_uri statements, they all assume that @html_file is a URI or a path.

So this change allows to override and use the @base_dir for assets when :with_html_string is used.

@rykov

@akzhan What do you think?

@rjocoleman

I'm coming up against this issue too.

My use case is being able to set the :base_dir when using :with_html_string - I'm using premailer to automate processing from my local development to production environments and as part of that directories need to change.

This PR is a little hard to follow and is currently conflicted so I'm happy to refactor this so that it fits requirements.

@akzhan what do you need here for this to be merged?

@rykov

It looks like the latest implementation removes @base_url from the href and makes it a relative path within the current directory.

if @options[:with_html_string]
  link_uri = tag.attributes['href'].to_s.sub(@base_url.to_s, '').sub(/\A\/*/, '')

And then the path is loaded later with:

if Premailer.local_data?(link_uri)
  $stderr.puts "Loading css from local file: " + link_uri if @options[:verbose]
  load_css_from_local_file!(link_uri)

Is that not working? It might be because load_css_from_local_file! is not resolving the path to @base_dir and rather uses the current directory of your script execution (which may be anything).

So the new fix will probably need to add something like this to load_css_from_local_file which will resolve relative paths to @base_dir and not touch absolute ones:

path = File.expand_path(path, @base_dir)
@rjocoleman

Thanks for the clarification @rykov I was wrong - my use case is similar at first look but actually quite different.

I needed to rewrite my relative URLs to absolute with a different directory path (prepending a directory specifically) I thought `"base_dir" might assist with this. I've taken the route of passing my html though nokogiri first to do this then passing the output as a sting to premailer. I omit 'base_url' entirely and it performs as I need.

In short sorry for dredging this up, I was off base entirely!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Commits on Jul 29, 2012
  1. @rykov
This page is out of date. Refresh to see the latest.
Showing with 4 additions and 3 deletions.
  1. +4 −3 lib/premailer/premailer.rb
View
7 lib/premailer/premailer.rb
@@ -193,6 +193,7 @@ def initialize(html, options = {})
:line_length => 65,
:link_query_string => nil,
:base_url => nil,
+ :base_dir => nil,
:remove_classes => false,
:remove_ids => false,
:remove_comments => false,
@@ -221,7 +222,7 @@ def initialize(html, options = {})
@css_warnings = []
@base_url = nil
- @base_dir = nil
+ @base_dir = @options[:base_dir]
@unmergable_rules = nil
if @options[:base_url]
@@ -298,8 +299,8 @@ def load_css_from_html! # :nodoc:
# A user might want to <link /> to a local css file that is also mirrored on the site
# but the local one is different (e.g. newer) than the live file, premailer will now choose the local file
- if tag.attributes['href'].to_s.include? @base_url.to_s and @html_file.kind_of?(String)
- link_uri = File.join(File.dirname(@html_file), tag.attributes['href'].to_s.sub!(@base_url.to_s, ''))
+ if tag.attributes['href'].to_s.include? @base_url.to_s and @is_local_file
+ link_uri = File.join(@base_dir || '', tag.attributes['href'].to_s.sub!(@base_url.to_s, ''))
end
# if the file does not exist locally, try to grab the remote reference
Something went wrong with that request. Please try again.