Commit Graph

355 Commits

Author SHA1 Message Date
Ted
0c528034cf
Update actionview/CHANGELOG.md
Co-authored-by: Petrik de Heus <petrik@deheus.net>
2021-07-12 09:16:25 -07:00
Ted
141a0859f8
Add CHANGELOG message for PR #41283 2021-07-11 19:04:52 -07:00
Ryuta Kamizono
91593af849 Merge pull request #41559 from jonathanhefner/sms_to-country_code
Add :country_code option to sms_to
2021-07-03 11:19:20 +09:00
Dirkjan Bussink
0523532a3c
Always use OpenSSL constants for Digest operations
As also previously discussed in
https://github.com/rails/rails/pull/40770#issuecomment-748347066, this
moves the usage of Digest constants to always use the OpenSSL version of
those Digest implementations.
2021-06-30 13:57:54 +02:00
Jonathan Hefner
dd884eb425 Pass default values for translate through I18n
A default value can be a string that needs interpolation, Hash that
needs resolution via the `:count` option, or a Proc that needs
evaluation.  Therefore, pass default values through `I18n.translate` to
handle these cases.

Fixes #26032.
Fixes #41277.
Fixes #41380.
2021-04-30 09:25:41 -05:00
Abhay Nikam
2005afbe04 Adds option extname to stylesheet_link_tag to exclude automatically appended .css extension.
Fixes: #41918

This PR adds the option `extname` to `stylesheet_link_tag`.
Previously, `stylesheet_link_tag` automatically added `.css`.
2021-04-29 11:20:14 +05:30
Jonathan Hefner
b9eb9fee64 Add :country_code option to sms_to
`phone_to` supports a `:country_code` option, so add a `:country_code`
option to `sms_to` for consistency.
2021-04-03 10:44:37 -05:00
Petrik
96d72d9b25 Deprecate render locals to be assigned to instance variables
Rails partial rendering allows assigning instance variables.
For example:

  render 'partial', :@name => "Maceo"

This sets @name to "Maceo" on the ActionView::Base object.

The allowed instance variables aren't restricted to the user's defined
instance variables but can also override private Rails variables like
@_assigns, @output_buffer, @_config, and @_default_form_builder.
2021-02-16 20:06:59 +01:00
Rafael Mendonça França
bf545b73b7
Add CHANGELOG entry for #41215 2021-01-27 00:33:12 +00:00
Sean Doyle
b8c9c9d06f Translate FormBuilder#button calls with formmethod:
When submitting a `<form>`, browsers will serialize the element that
initiated the submission as part of the [FormData][], including its
`name` and `value` attributes.

Browser support for `<form>` submission HTTP verbs is limited to `GET`
and `POST`. Rails currently works around this [limitation by
constructing `<input type="hidden" name="_method" value="VERB">` which
serializes `_method="VERB"` to the FormData][_method].

To support varied HTTP actions within the same form, this commit
intervenes when a `form.button formmethod: "..."` call is made during
form construction, and translates any `formmethod:` value to the
corresponding work-around version.

[FormData]: https://developer.mozilla.org/en-US/docs/Web/API/FormData
[_method]: https://edgeguides.rubyonrails.org/form_helpers.html#how-do-forms-with-patch-put-or-delete-methods-work-questionmark
[button-formmethod]: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/button#attr-formmethod
2021-01-08 18:21:02 -05:00
Ryuta Kamizono
401ce9dd3d Tweak CHANGELOGs [ci skip]
* Remove trailing space
* Add period
* etc
2020-12-29 21:11:16 +09:00
Sean Doyle
9af9458396 Consistently render button_to as <button>
Prior to this commit, the
[ActionView::Helpers::UrlHelper#button_to][button_to] helper rendered
`<input type="submit">` elements when passed its contents as a String
argument, and rendered `<button type="submit">` elements when passed its
contents as a block.

This difference is subtle, and might lead to surprises.

Additionally, a `<form>` element's submitter can encode a `name`/`value`
pairing, which will be submitted as part of the request. When
`button_to` renders an `<input type="submit">` element, the "button"
content is rendered as a `[value]` attribute, which prevents any
meaningful data from being encoded.

Since it's a single `<button>` or `<input type="submit">` within a
`<form>`, missing out on that opportunity to encode information might
not be a show stopper, but ensuring that a `<button>` element is
rendered _without_ a default `[value]` attribute enables applications to
encode additional information that can be accessed JavaScript as
`element.value`, instead of a workaround like
`element.getAttribute("data-value")`.

Support rendering `input` elements with button_to
---

To support the original behavior of `button_to` rendering `<input
type="submit">` elements when invoked _without_ a block, expose the
`app.config.button_to_generates_button_tag` configuration flag.

By default, it's set to `true` and ensures that all `button_to` calls
render `<button>` elements. To revert to the original behavior, set it
to `false`.

[button_to]: https://api.rubyonrails.org/v6.0/classes/ActionView/Helpers/UrlHelper.html#method-i-button_to

Co-authored-by: Dusan Orlovic <duleorlovic@gmail.com>
2020-12-28 19:33:05 -05:00
Andrew White
200083c232
Add config.action_view.preload_links_header option
PR #39939 added support for the `Link` header being generated
automatically when using `stylesheet_link_tag` and
`javascript_include_tag`. However not everything should be
preloaded, e.g. a link to a legacy IE stylesheet has no need to be
preloaded because IE doesn't support the header and in some browsers it
will trigger the preload even though it's not used since it's inside an
IE conditional comment. This leads to increased bandwith costs and
slower application performance.

To allow more flexibility for sites that may have complex needs for the
`Link` header this commit adds a configuration option that disables it
completely and leaves it up to the application to decide how to handle
generating a `Link` header.
2020-12-19 05:24:09 +00:00
Jonathan Hefner
b8b18bbfad Handle nil translation key
`I18n.translate` returns `nil` when given a `nil` key, *unless* a
`default` is also specified.  If a `default` is specified, the `nil` key
is treated as a missing key.

In Rails 6.0, the `translate` helper always returned `nil` when given a
`nil` key.  After #40773, the `translate` helper always raised an
`I18n::ArgumentError` when given a `nil` key.  This commit fixes the
`translate` helper to mirror the `I18n.translate` behavior when given a
`nil` key, with and without a `default`.
2020-12-10 11:51:32 -06:00
Rafael Mendonça França
2a41b6ea98
Add CHANGELOG entry for #38452
[ci skip]
2020-12-09 00:12:51 +00:00
Rafael Mendonça França
59f7f5889e
Start Rails 6.2 development 🎉 2020-12-03 01:35:29 +00:00
Petrik
0a583c73c1 Change form_with to generate non remote forms by default
`form_with` would generate a remote form by default.
This confused users because they were forced to handle remote requests.

All new 6.1 applications will generate non-remote forms by default.
When upgrading a 6.0 application you can enable remote forms by default by
setting `config.action_view.form_with_generates_remote_forms` to `true`.
2020-12-01 21:14:37 +01:00
Sean Doyle
59ca21c011 Declare ActionView::Helpers::FormBuilder#id
`ActionView::Helpers::FormBuilder#id`
---

Generate an HTML `id` attribute value.

Return the [`<form>` element's][mdn-form] `id` attribute.

```html+erb
<%= form_for @post do |f| %>
  <%# ... %>

  <% content_for :sticky_footer do %>
    <%= form.button(form: f.id) %>
  <% end %>
<% end %>
```

In the example above, the `:sticky_footer` content area will exist
outside of the `<form>` element. [By declaring the `form` HTML
attribute][mdn-button-attr-form], we hint to the browser that the
generated `<button>` element should be treated as the `<form>` element's
submit button, regardless of where it exists in the DOM.

[A similar pattern could be used for `<input>`
elements][mdn-input-attr-form] (or other form controls) that do not
descend from the `<form>` element.

`ActionView::Helpers::FormBuilder#field_id`
---

Generate an HTML <tt>id</tt> attribute value for the given field

Return the value generated by the <tt>FormBuilder</tt> for the given
attribute name.

```html+erb
<%= form_for @post do |f| %>
  <%= f.label :title %>
  <%= f.text_field :title, aria: { describedby: form.field_id(:title, :error) } %>
  <span id="<%= f.field_id(:title, :error) %>">is blank</span>
<% end %>
```

In the example above, the <tt><input type="text"></tt> element built by
the call to <tt>FormBuilder#text_field</tt> declares an
<tt>aria-describedby</tt> attribute referencing the <tt><span></tt>
element, sharing a common <tt>id</tt> root (<tt>post_title</tt>, in this
case).

This method is powered by the `field_id` helper declared in
`action_view/helpers/form_tag_helper`, which is made available for
general template calls, separate from a `FormBuilder` instance.

[mdn-form]: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/form
[mdn-button-attr-form]: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/button#attr-form
[mdn-input-attr-form]: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input#attr-form
[mdn-aria-describedby]: https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/ARIA_Techniques/Using_the_aria-describedby_attribute
[w3c-wai]: https://www.w3.org/WAI/tutorials/forms/notifications/#listing-errors
2020-11-30 18:47:49 -05:00
Sean Doyle
7503ef9490
Escape HTML attributes for ERB interpolation (#40657)
Transforms a Hash into HTML Attributes, ready to be interpolated into
ERB.

```html+erb
<input <%= tag.attributes(type: :text, aria: { label: "Search" }) %> >
<%# => <input type="text" aria-label="Search"> %>
```

Utilizes the `ActionView::Helpers::TagHelper#tag_options` implementation
to enable combining ERB with attribute transformation, without requiring
templates to replace HTML strings with `tag` or `content_tag`
invocations.

Co-authored-by: David Heinemeier Hansson <david@loudthinking.com>
2020-11-28 11:01:15 +01:00
Rafael Mendonça França
8389f9902c
Preparing for 6.1.0.rc1 release 2020-11-02 21:12:47 +00:00
Sean Doyle
a086418283 Yield translation to FormBuilder#button block
When translating a `<button>` element's contents, it is tedious  to make
the translation text available to a block scope.

For instance, when rendering a `<button type="submit">` with an SVG
element as its child, passing translated label text to that SVG
element's [`<title>`][svg-title] element requires an extra call to
`I18n.translate`.

Prior to this commit, doing so would require a double lookup of the
translation key:

```erb
<%# one time here, implicitly %>
<%= form.button do %>
  <svg>
    <title>
      <!-- one time here, explicitly -->
      <%= translate("helpers.submit.post.create") %>
    </title>
    <!-- ... -->
  </svg>
<% end %>
```

This commit modifies the `ActionView::Helpers::FormBuilder#button` to
check for invocations that are passed a block, and conditionally yield
the contents of `submit_default_value` as the argument.

The new view code might look something like this:

```erb
<%= form.button do |text| %>
  <svg>
    <title><%= text %></title>
    <!-- ... -->
  </svg>
<% end %>
```

Callers of the helper are still free to omit the block parameter.

[svg-title]: https://developer.mozilla.org/en-US/docs/Web/SVG/Element/title
2020-10-30 16:30:56 -04:00
Sean Doyle
d38c214b75 Yield Tags::Label::LabelBuilder#translations
When translating a `<label>` element's contents, it is difficult (or
"possible", yet undocumented) to make the translation text available to
a block scope.

For instance, when rendering a `rich_text_area`, passing the
`aria-label` attribute might be important.

Prior to this commit, doing so would require a double lookup of the
translation key:

```erb
<%# one time here, implicitly %>
<%= form.label(:content) do %>
  <%= form.rich_text_area(
    :content,
    # one time here, explicitly
    "aria-label" => translate("helpers.label.post.content"),
  ) %>
<% end %>
```

The current implementation of the `#label` helper method already yields
an instance of `ActionView::Helpers::Tags::Label::LabelBuilder`, but
that class is undocumented. Instance of that class respond to
`#translation` calls, which will return the translated text content.

By aliasing `#translation` to `#to_s`, we're able to expose that value
without the burden of exposing an additional class to the public API.
Instead, view-level interpolation (either `<%= %>`, `#{ }`, or direct
calls to [`capture`][capture] will coerce the value to a String, and
implicitly invoke `#translation`.

The new view code might look something like this:

```erb
<%= form.label(:content) do |label| %>
  <%= form.rich_text_area(:content, "aria-label" => label) %>
<% end %>
```

Callers of the helper are still free to omit the block parameter.

[capture]: https://api.rubyonrails.org/classes/ActionView/Helpers/CaptureHelper.html#method-i-capture
2020-10-30 15:59:56 -04:00
Sean Doyle
67409e03a4 Alias TagHelper#class_names to #token_list
Rename the new `TagHelper#class_names` method to `TagHelper#token_list`,
and make the original available as an alias.

Inspired by a discussion on [rails/rails#40121][]

Once rendered by a browser, [an element's `class` attribute is
represented as a `DOMTokenList`][mdn-domtokenlist]. It's a
space-delimited list with unique elements.

Outside of the HTML `[class]` attribute, there are other attributes that
are represented as space-delimited lists. A non-exhaustive list
includes:

* [aria-labelledby][mdn-aria-labelledby]
* [aria-describedby][mdn-aria-describedby]
* [data-controller][data-controller] (in StimulusJS applications)
* [data-action][data-action] (in StimulusJS applications)

To support these attributes, ensure the collection of values from the
`class_names` helper is a unique Set.

[rails/rails#40121]: https://github.com/rails/rails/pull/40121#issuecomment-683366103
[class_names]: https://edgeapi.rubyonrails.org/classes/ActionView/Helpers/TagHelper.html#method-i-class_names
[mdn-aria-labelledby]: https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/ARIA_Techniques/Using_the_aria-labelledby_attribute#Value
[mdn-aria-describedby]: https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/ARIA_Techniques/Using_the_aria-describedby_attribute#Value
[data-action]: https://stimulusjs.org/reference/actions
[data-controller]: https://stimulusjs.org/reference/controllers
2020-10-30 13:20:13 -04:00
Sean Doyle
8b19d66fc6 Serialize aria- namespaced list attributes
Summary
===

Prior to this commit, calls passing `aria: { labelledby: [...] }`
serialized the `aria-labelledby` Array value as JSON.

This commit introduces special case logic to serialize `aria-` prefixed
`TrueClass`, `FalseClass`, `Hash`, and `Array` values more
appropriately.

An element's [`aria-labelledby` attribute][aria-labelledby] and
[`aria-describedby` attribute][aria-describedby] can accept a
space-delimited list of identifier values (much like the [`class`
attribute][class] accepts a space delimited [`DOMTokenList`
value][DOMTokenList]).

Similarly, there are [no boolean `aria-` attributes][aria-attributes]
(only `true`, `false`, or undefined), so this commit serializes `true`
to `"true"` and `false` to `"false"`.

Testing
---

This change moves an assertion _outside_ of a loop over `["aria",
:aria]`. Prior to this change, the second assertion within the loop
wasn't utilizing the iterated value as a Hash key. That is to say:
`aria:` (where an `aria` local variable is declared) is not equivalent
an equivalent syntax to `aria =>`.

Since the migration to `**options` in response to Ruby 2.7 deprecations,
invoking `tag.a("aria" => {...})` incorrectly coerces the `"aria" =>
{...}` has to be the `TagBuilder#a` method `content = nil` ordered
argument, instead of its `options` keyword arguments. This commit does
not modify that behavior, but it _does_ move the assertion outside the
block so that it isn't run unnecessarily.

[aria-labelledby]: https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/ARIA_Techniques/Using_the_aria-labelledby_attribute
[aria-describedby]: https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/ARIA_Techniques/Using_the_aria-describedby_attribute
[aria-attributes]: https://www.w3.org/TR/wai-aria-1.1/#propcharacteristic_value
[class]: https://developer.mozilla.org/en-US/docs/Web/HTML/Global_attributes/class
[DOMTokenList]: https://developer.mozilla.org/en-US/docs/Web/API/DOMTokenList
[class_names]: https://edgeapi.rubyonrails.org/classes/ActionView/Helpers/TagHelper.html#method-i-class_names
2020-10-29 21:55:33 -04:00
Rafael Mendonça França
6583895ebe
Remove deprecated escape_whitelist from ActionView::Template::Handlers::ERB 2020-10-30 00:25:30 +00:00
Rafael Mendonça França
dafa49bb4c
Remove deprecated find_all_anywhere from ActionView::Resolver 2020-10-30 00:25:29 +00:00
Rafael Mendonça França
db5a2dfe3e
Remove deprecated formats from ActionView::Template::HTML 2020-10-30 00:25:29 +00:00
Rafael Mendonça França
6124294684
Remove deprecated formats from ActionView::Template::RawFile 2020-10-30 00:25:28 +00:00
Rafael Mendonça França
217eb5dc4a
Remove deprecated formats from ActionView::Template::Text 2020-10-30 00:25:27 +00:00
Rafael Mendonça França
71904857d4
Remove deprecated find_file from ActionView::PathSet 2020-10-30 00:25:27 +00:00
Rafael Mendonça França
b57e227f6d
Remove deprecated rendered_format from ActionView::LookupContext 2020-10-30 00:25:26 +00:00
Rafael Mendonça França
806e4874f5
Remove deprecated find_file from ActionView::ViewPaths 2020-10-30 00:25:25 +00:00
Rafael Mendonça França
469c4ccad7
Require that ActionView::Base subclasses implement #compiled_method_container 2020-10-30 00:25:24 +00:00
Rafael Mendonça França
05f234dbbd
Remove deprecated support to pass an object that is not a ActionView::LookupContext as the first argument in ActionView::Base#initialize 2020-10-30 00:25:23 +00:00
Rafael Mendonça França
c3b08725a1
Remove deprecated format argument ActionView::Base#initialize 2020-10-30 00:25:22 +00:00
Rafael Mendonça França
db82d4da62
Remove deprecated ActionView::Template#refresh 2020-10-30 00:25:21 +00:00
Rafael Mendonça França
9d2a0c903d
Remove deprecated ActionView::Template#original_encoding 2020-10-30 00:25:21 +00:00
Rafael Mendonça França
d6575dc42e
Remove deprecated ActionView::Template#variants 2020-10-30 00:25:20 +00:00
Rafael Mendonça França
2a10775ac1
Remove deprecated ActionView::Template#formats 2020-10-30 00:25:19 +00:00
Rafael Mendonça França
aa7d6f0c64
Remove deprecated ActionView::Template#virtual_path= 2020-10-30 00:25:19 +00:00
Rafael Mendonça França
b88615e875
Remove deprecated ActionView::Template#updated_at 2020-10-30 00:25:18 +00:00
Rafael Mendonça França
d25840eb49
Make locals argument required on ActionView::Template#initialize 2020-10-30 00:25:17 +00:00
Rafael Mendonça França
71ddfd78d4
Remove deprecated finalize_compiled_template_methods 2020-10-30 00:25:16 +00:00
Rafael Mendonça França
0de9560e3e
Remove deprecated support to calling ActionView::ViewPaths#with_fallback with a block 2020-10-30 00:25:16 +00:00
Rafael Mendonça França
2759addf2c
Remove deprecated support to passing absolute paths to render template: 2020-10-30 00:25:15 +00:00
Rafael Mendonça França
d52d773946
Remove deprecated support to passing relative paths to render file: 2020-10-30 00:25:14 +00:00
Rafael Mendonça França
4d77dcad09
Remove support to template handlers that don't accept two arguments 2020-10-30 00:25:13 +00:00
Rafael Mendonça França
320e7f7c95
Remove deprecated pattern argument in ActionView::Template::PathResolver 2020-10-30 00:25:13 +00:00
Rafael Mendonça França
5b8fe6c37e
Remove deprecated support to call private methods from object in some view helpers 2020-10-30 00:25:11 +00:00
Sean Doyle
7cf52ae981
Extend ActionView::Helpers#translate to yield
This commit extends the `ActionView::Helpers#translate` (and by way of
alias, `#t`) helper methods to accept blocks.

When invoked with a block, the `translate` call will yield the
translated text as its first block argument, along with the resolved
translation key as its second:

```erb
<%= translate(".key") do |translation, resolved_key| %>
  <span data-i18n-key="<%= resolved_key %>"><%= translation %></span>
<% end %>
```

In cases where relative translation keys are foregone in lieu of fully
qualified keys, or if the caller is not interested in the resolved key,
the second block argument can be omitted:

```erb
<%= translate("action.template.key") do |translation| %>
  <p><%= translation %></p>
  <p><%= translation %>, but a second time</p>
<% end %>
```

A benefit of yielding the translation is that it enabled template-local
variable re-use. Alternatively, [`Object#tap`][tap] could be used.

Prior to this commit, however, the resolution of the translation key was
internal to `ActionView`, and unavailable to the caller (unless they
were willing to explicitly determine the resolved key themselves). By
making it available as a block parameter, it could be used to annotate
the translated value in the resulting elements.

[tap]: https://ruby-doc.org/core-2.7.0/Object.html#method-i-tap
2020-08-26 20:46:33 +00:00