Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Make Emoji img attributes configurable #258

Closed
wants to merge 3 commits into from

Conversation

JuanitoFatas
Copy link
Contributor

@JuanitoFatas JuanitoFatas commented Jun 28, 2016

Resolves #234

This Pull Request makes img tag attributes configuarable:

@jch What do you think?

@@ -71,7 +71,42 @@ def asset_path(name)

# Build an emoji image tag
def emoji_image_tag(name)
"<img class='emoji' title=':#{name}:' alt=':#{name}:' src='#{emoji_url(name)}' height='20' width='20' align='absmiddle' />"
"<img #{img_html_attrs(name)}>"
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm wary of this change because unsafe user input could be injected here. Could you look whitelisting only attributes that make sense for a img element?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm wary of this change because unsafe user input could be injected here.

This is not from user input. It is context option used by developer.

Could you look whitelisting only attributes that make sense for a img element?

ditto, let's leave this to developer?

Copy link
Contributor

@jch jch Jun 29, 2016

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good point. I missed that.

  • Could you update the documentation at the top of the class explaining this new context option?
  • What do you think about simplifying the methods? The new methods are not part of the public interface, and I feel they add more layers than necessary. What about doing this new work in the existing emoji_image_tag method?

edit noticed the new methods are private, but still feel they add too many layers.

@JuanitoFatas
Copy link
Contributor Author

@jch Thanks for the review, updated in 1b3e5e4 :)

context[:img_attrs].each do |key, value|
context[:img_attrs][key] = value.call(name) if value.respond_to?(:call)
end
end
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This method can be inlined as well. Similar reasoning as before. Here, we're mutating the context hash by adding more elements to it. While that's doable, it makes it difficult to debug pipelines because it's unclear which filter modified a context. Instead, we can leave the context as passed in options and use it's values. I haven't tested this, but I imagine something like:

default_attrs = default_img_attrs(name)

# This avoids creating an extra empty hash for each invocation and only merges if user passed something in
merged_attrs = context[:img_attrs] ? default_attrs.merge(context[:img_attrs]) : default_attrs

# This builds the attributes and handles procs. In your implementation, you remove nils, but I think that should be the responsibility of the caller. Nils would print as an empty value, which would still be valid.
html_attrs = merged_attrs.map do |k, v| 
  "#{k}='#{v.try(:call) || v}'"
end

"<img #{html_attrs.join(' '}>"

Copy link
Contributor Author

@JuanitoFatas JuanitoFatas Jun 30, 2016

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This method can be inlined as well. Similar reasoning as before. Here, we're mutating the context hash by adding more elements to it. While that's doable, it makes it difficult to debug pipelines because it's unclear which filter modified a context

👍 Awesome!

Instead, we can leave the context as passed in options and use it's values. I haven't tested this, but I imagine something like:

I adapt your imagination as f1c1618.

In your implementation, you remove nils, but I think that should be the responsibility of the caller. Nils would print as an empty value, which would still be valid.

This is because #234, user of HTML::Pipeline need to clear some unwanted default attributes to pass the W3C validations.

Another change I added is indifferent access to context[:img_attrs] hash .

Why? Because a user may be tempted to use { height: nil, width: nil } to clear height and width attributes. Without indifferent access, the keys of Hash must be String. Better developer experience in my opinion.

1. User can specify a hash `context[:img_attrs]` to change the `img` tag
attributes, e.g. `{ "draggable" => false }`

2. The hash key can be either `String` / `Symbol` (indifferent access)

  `{ "draggable" => false }` / `{ draggable: false }`

  =>

  `<img draggable="false">`

3. The hash value can be either anything / proc-like object

  Proc-like object with default argument `name`:

  Given name is `:shipit:`

  `{ title: ->(name) { |n| n.gsub(":", "") } }`

  =>

  `<img title="shipit">`

  So you can do any customisations with the attribute.

4. The hash value nil means clear the attribute of img tag

  For example, to clear the default `height`, `width`, and `align`
  attributes, pass `{ height: nil, width: nil, align: nil }` to
  `context[:img_attrs]`.

5. Refine tests with consistent styles
@JuanitoFatas
Copy link
Contributor Author

JuanitoFatas commented Jun 30, 2016

If you think this is mergable, I will squash commits, merge into master. Add an changelog item and release a patch version :)

@jch
Copy link
Contributor

jch commented Jun 30, 2016

I will squash commits, merge into master. Add an changelog item and release a patch version :)

Sounds good! Thanks for tackling this.

@JuanitoFatas
Copy link
Contributor Author

Merged as 3518bbb.

@JuanitoFatas JuanitoFatas deleted the feature/custom-img-attrs branch July 1, 2016 07:02
JuanitoFatas referenced this pull request Jul 1, 2016
1. User can specify a hash `context[:img_attrs]` to change the `img` tag
attributes, e.g. `{ "draggable" => false }`

2. The hash key can be either `String` / `Symbol` (indifferent access)

  `{ "draggable" => false }` / `{ draggable: false }`

  =>

  `<img draggable="false">`

3. The hash value can be either anything / proc-like object

  Proc-like object with default argument `name`:

  Given name is `:shipit:`

  `{ title: ->(name) { |n| n.gsub(":", "") } }`

  =>

  `<img title="shipit">`

  So you can do any customisations with the attribute.

4. The hash value nil means clear the attribute of img tag

  For example, to clear the default `height`, `width`, and `align`
  attributes, pass `{ height: nil, width: nil, align: nil }` to
  `context[:img_attrs]`.

5. Refine tests with consistent styles
@kbrock
Copy link
Contributor

kbrock commented Jul 13, 2016

Thank you @JuanitoFatas - this was a much needed feature and looks great

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants