Follow-up from #552478: Restrict "self-closing" tags to only void elements in drupal_pre_render_html_tag.
Motivation
HTML5 does not actually implement the concept of "self-closing tags". It is a relic from XHTML. From http://www.w3.org/TR/html5/syntax.html#syntax-start-tag:
Then, if the element is one of the void elements, or if the element is a foreign element, then there may be a single "/" (U+002F) character. This character has no effect on void elements, but on foreign elements it marks the start tag as self-closing.
It has "no effect on void elements", meaning it is ignored when being parsed.
Proposed resolution
Remove all unnecessary /
characters from void elements in core-provided templates, documentation, sources and output:
area, base, br, col, embed, hr, img, input, keygen, link, meta, param, source, track, wbr
This DOES NOT (and should not) include user generated content. For example, if a content editor inserts a <br />
tag into a body of a node, it should be preserved by filter as is.
Remaining tasks
- Document self-closing tags usage in coding standards both for HTML and JS.
Documentation should clearly describe the difference between void tags and foreign elements, as well as the usage of<div />
syntax in JS. - Can templates in
stable
theme be modified in minor release? - Remove self-closing void tags from output of
filter
module without breaking its current behavior.
Filters should not forcibly remove the closing slash if it is added by user, but they should not forcibly add it in either. - Reconfigure editor to not generate these tags in content and update tests in
editor
module. - Test the behavior of
Drupal\Core\Mail\MailFormatHelper::htmlToText
to make sure that it can transform both cases. - Update XSS filtering tests to verify that they cover both normal and self-closing void tags (i.e.
core/tests/Drupal/Tests/Component/Utility/XssTest.php
). - Decide if it is necessary to remove self-closing tags from test fixtures.
A quote from @sun's comment #48 on migrations:
The D6 source configuration may contain self-closing tags, so migration tests should not be changed.
That said, perhaps we want to process such config in a way to automatically adjust self-closing tags during the migration, but that should be discussed in a separate/dedicated issue.
User interface changes
None
API changes
None
Template changes
Changes in stable
, classy
, bartik
theme templates and default module templates.
Original report by @tim.plunkett
There are 11 uses of <br>
in core, and 87 of <br />
. I've never once used the latter, and both are valid HTML: http://dev.w3.org/html5/spec-author-view/syntax.html#syntax-start-tag
I propose core switch everything to <br>
.
Either way, we should pick one for core, and clarify in the coding standards that one is preferred but both are allowed.
Comment | File | Size | Author |
---|---|---|---|
#108 | interdiff.1388926.106-108.txt | 1.07 KB | longwave |
#108 | 1388926-108.patch | 20.13 KB | longwave |
Comments
Comment #1
JacineTagging. Sorta related: #552478: Restrict "self-closing" tags to only void elements in drupal_pre_render_html_tag
Comment #2
dcmouyard CreditAttribution: dcmouyard commented+1 for standardizing on
<br>
instead of<br />
.I assume this applies to other self-closing tags as well. (
<img>, <input>, <hr>, <link> <meta>
, etc.)Comment #3
dcmouyard CreditAttribution: dcmouyard commentedComment #4
droplet CreditAttribution: droplet commentedLuckily, D7 only used it on test.
Personally, I suggest
<br />
-
<br />
already in CORE (may not a very good point ^_^)-
<br />
is a standard in XHTML, I think most themer preferred it. (Myself never tried to type<br>
in pass few years)- adaption of XHTML X.0 version ?
Comment #5
tim.plunkettThe current usages are irrelevant. All of it could be trivially switched with some regex.
XHTML is dead, long live HTML.
Comment #6
gg4 CreditAttribution: gg4 commentedhttp://drupal.org/node/1089770
Guiding Principles
Below are the principles we will follow when developing HTML5 functionality for Drupal.
8. Mimic XHTML. Be HTML.
<br />
fits both criteria and gets my vote.Comment #7
Anonymous (not verified) CreditAttribution: Anonymous commentedSince both
<br>
and<br />
are equally valid in HTML, I'd say it's best to mimic XHTML and ruffle fewer feathers. Let's go with<br />
.Also, @tim.plunkett, if you haven't once used the latter, it's because you aren't old like us oldies... IIRC, it was what Zeldman recommended in Designing with Web Standards back in the day (2003) and usage was how you knew if someone was a cool kid or not :-P
Comment #8
ericduran CreditAttribution: ericduran commentedYea, I too always prefer the self closing tag
<br />
.This is one of those case like the required tag, it can be required or required="required" but we've decided to go with required="required"
Comment #9
adnasa CreditAttribution: adnasa commentedI disagree on switching
<br/>
to<br>
for personal preferences but I also think that themers would prefer self-omitting tags. keep the<br/>
Comment #10
cosmicdreams CreditAttribution: cosmicdreams commentedDoesn't sound like this patch would be terrible hard. Just a find and replace. Tagging for Novice and putting this on my plate for tonight.
Comment #11
cosmicdreams CreditAttribution: cosmicdreams commentedI just did a search on D8 and I couldn't find a single problem with the use of proper line breaks. I found a handful of issues wher "
" was used in the description of allowed html tags or in tests. But I didn't find an issue where the
was actually being outputted as markup.
I recommend we close (works as designed) this.
Comment #12
NROTC_Webmaster CreditAttribution: NROTC_Webmaster commentedI'm not sure what you mean by problems but it is referenced in several places in core.
Comment #13
tim.plunkettBut in none of those places is it actually used, and it probably shouldn't be replaced.
Comment #14
cosmicdreams CreditAttribution: cosmicdreams commented@NROTC_Webmaster I think I found those lines as well, look at those lines in context and I think you'll see that these lines don't refer to code that outputs markup for any of our components. It's all either (an appropriate) comment, help text to the user, or used in valid tests.
That's what I'm trying to say. This issue isn't productive.
Comment #15
NROTC_Webmaster CreditAttribution: NROTC_Webmaster commentedI don't have a personal preference I just wanted to make sure everyone was aware that it was still reference in core.
Comment #16
Anonymous (not verified) CreditAttribution: Anonymous commentedSo it sounds like this is no longer an issue in D8. Closing, feel free to reopen if it is still an issue.
Comment #17
markhalliwell226 usages in core/modules alone. Granted not all of it may be valid (ie: XML in aggregator.module), but there is definitely a ton still left in core.
system.install (ln 316):
Also, we really shouldn't be promoting older XHTML styles moving forward (regardless if they're not being used as "output").
Comment #18
markhalliwellComment #19
dinarcon CreditAttribution: dinarcon commentedWorking on it.
Comment #20
dinarcon CreditAttribution: dinarcon commentedI change one instance of a br tag. Is this the way that should be done?
Comment #21
markhalliwellYes
Comment #22
dinarcon CreditAttribution: dinarcon commentedThanks Mark. I'll continue working on this.
Comment #23
dinarcon CreditAttribution: dinarcon commentedI'm updating the br tags and I got some questions on the process.
1. Should we update the test files too? Files like core/modules/filter/src/Tests/FilterUnitTest.php test for the presence of the closing slash '/'.
2. Filter module checks for '<br />' in the _filter_autop() function. They should not be updated, right?
Comment #24
markhalliwell1. Ultimately, yes. However, this will require modifying several possible theme hooks (templates/functions) and what they output. This in reality should probably be a separate issue.
2. No. Do not take out
<br />
from the filter functions of filter.module. However, if there is output that is for the actual page itself (provided by core, not user input).. then yes.FYI, setting to "Needs review" will trigger the test bot.
Comment #26
dinarcon CreditAttribution: dinarcon commentedThanks Mark. I'll continue on this.
I'll leave test assertions for another issue then. I won't update filter module's either, unless it is output for the page.
Comment #27
dinarcon CreditAttribution: dinarcon commentedI have updated most tags on the core/modules and core/themes directories.
Some more questions:
1. In core/modules/filter/src/Tests/FilterUnitTest.php there are assertions that test the addition of the closing slash. They are under the 'HTML corrector -- XHTML closing slash.' group. Is the filter module adding those closing slash back? Anything to be done about this?
2. In core/modules/system/templates/table.html.twig there is a colgroup tag without child elements. Is it correct?
Comment #28
RainbowArrayI think what you'd want for filters is that they don't forcibly remove the closing slash, but they shouldn't forcibly add it in either.
Colgroup can have no child elements. But it's not a void element, so you'd want to still have an end tag.
Comment #29
dinarcon CreditAttribution: dinarcon commentedThanks Mark.
This is a new patch with the end tag for colgroup. I think the filter functionality might be addressed in another issue. Please let me know otherwise.
Comment #30
martin107 CreditAttribution: martin107 commentedComment #31
outlierdavid CreditAttribution: outlierdavid commentedI am at the Austin Sprint. I am working on this issue and have found some additional self closing void tags. Creating patch now.
Comment #32
outlierdavid CreditAttribution: outlierdavid commentedRan this regex in the /core/modules folder to find the stuff fixed in the patch:
<(area|img|base|br|col|embed|hr|input|keygen|link|meta|param|source|track|wbr)(.*)/>
I did not apply this regex to the "filters" module. If you want to, run the regex above on that folder in your IDE. :)
Comment #34
outlierdavid CreditAttribution: outlierdavid commented32: remove-self-closing-1388926-32.patch queued for re-testing.
Comment #36
outlierdavid CreditAttribution: outlierdavid commentedTesting new patch. Sorry for the failed attempts. :S
Comment #37
dinarcon CreditAttribution: dinarcon commentedComment #39
outlierdavid CreditAttribution: outlierdavid commentedTrying again.
Comment #40
lauriiiMarking this to Needs Review to get our test bots attention on this one ;)
Comment #41
lauriiiComment #42
outlierdavid CreditAttribution: outlierdavid commentedThanks man. Applied the patch on my local and reviewed a lot of it. Seems good to go.
Comment #44
lauriiiRemoved some self-closing elements.
Comment #45
lauriiiComment #46
joelpittetDoes this count as don't remove from filters? Mentioned in the issue summary.
Comment #48
sunYup, @joelpittet is right — some further issues:
If any changes to the paragraph filter are necessary, then those should be performed in a separate/dedicated issue.
Ditto for the Allowed HTML tags filter.
Ditto for the HTML corrector filter.
The D6 source configuration may contain self-closing tags, so migration tests should not be changed.
That said, perhaps we want to process such config in a way to automatically adjust self-closing tags during the migration, but that should be discussed in a separate/dedicated issue.
A DIV is not really self-closing.
At least I don't think we want to intentionally produce incomplete HTML in core.
This (outdated?) comment should probably not be changed, so the original intention of the code can be properly revisited later on.
These test cases are explicitly asserting that self-closing tags in the input HTML are properly converted into plain-text, so they should not be changed.
As above, I don't think we want to intentionally produce incomplete/bogus HTML here. A COLGROUP is not really self-closing; the UA rendering engine needs to correct the DOM first.
For this text summary test, the possible appearance of a self-closing tag attempts to cover an edge-case parsing/processing scenario, so the changes should be reverted.
Functional change, to be reverted.
This unit test method should probably be duplicated into a second, so that both possible syntax cases are covered.
Ideally in a separate issue, so as to not include any non-minor changes in this big conversion patch here.
Comment #49
joelpittetWe can let someone else grab this one, unassigning grab it again if you have the time to review #48
Comment #50
pakmanlhWorking on reroll from 44...
Comment #51
pakmanlhHere I rerolled patch taking into consideration comments on #48
Comment #53
pakmanlhWorking on remove modification on test files to pass test...
Comment #54
pakmanlhHere again the patch removin modifications from tests files.
Comment #56
pakmanlhSorry, I forgot the «FilterHtmlImageSecureTest» test modifications, here the patch again.
Comment #57
er.pushpinderrana CreditAttribution: er.pushpinderrana commentedComment #58
rteijeiro CreditAttribution: rteijeiro commentedI can still find some "self-closing" elements, for example:
core/modules/editor/src/Tests/QuickEditIntegrationLoadingTest.php ->
<img src="druplicon.png" />
core/includes/form.inc ->
$batch_set['init_message'] .= '<br/> ';
core/modules/system/src/Tests/Mail/HtmlToTextTest.php ->
'<br />Drupal<br />Drupal<br /><br />Drupal' => "Drupal\nDrupal\nDrupal\n",
You can use the following regexp in the command line to find a lot more:
rgrep --color '<img.*/>' core
Back to "needs work" sorry :(
Comment #59
pakmanlhHere a new patch including the rest of self-closing elements found out of core/vendor or tests folders.
Comment #60
star-szrAt a glance this kinda looks like it's changing the filter functionality.
Comment #61
LinL CreditAttribution: LinL commentedPatch no longer applies, tagging for reroll.
Comment #62
martin107 CreditAttribution: martin107 commentedReroll.
Comment #64
martin107 CreditAttribution: martin107 commentedFunctionsTest.php back to green ( after trivial fixup )
Comment #65
Jolidog CreditAttribution: Jolidog commentedReroll.
Comment #66
legolasboI'll review this patch right now.
Comment #67
legolasboI agree with @Cotser in #60. It looks like this changes the filter functionality. At least it breaks the resulting $line_breaks array.
$line_breaks = array('
' => 6, '
' => 4);
results in an array containing two elements.
$line_breaks = array('
' => 6, '
' => 4);
results in an array containing one element.
Besides that, the patch looks good to me.
Comment #68
legolasboComment #69
Hanno CreditAttribution: Hanno commentedfilter_autop currently insert
<br />
in texts, so yes, this would alter this filter asaik, we should change after this patch filter_autop to return<br>
as well.#2350049: filter_autop() returns <br /> but should return <br> for HTML5
Comment #70
a-fro CreditAttribution: a-fro commentedRerolled 65
Comment #71
joelpittetAddressing the comments from #48 that were missed and #60.
Undid the JS changes mentioned in #48 and the table colgroup tag.
Comment #72
akalata CreditAttribution: akalata commentedReviewing to confirm changes following the feedback in #48, I found the following:
core/modules/filter/src/Tests/FilterUnitTest.php
, but I don't think most of those changes should be here (if the filter.module changes are a separate issue)?should this change to FilterAutoP be in #2350049: filter_autop() returns <br /> but should return <br> for HTML5 instead?
Wondering if this change should also be moved?
And some new questions:
The
<video>
tag is not in the official list ofvoid
elements.Should these tests not remove the line, but just add a new one so it checks for both styles (until fitlers are updated)?
Same as above, though even if this change is kept I believe there's an error in the added line?
This last group of items was found using the regex provided in #23
$batch_set['init_message'] .= '<br/> ';
in core/includes/form.inc'#prefix' => "<br style='clear:both'/>",
in FileTransferAuthorizeForm$sample_picture = '<img src="' . file_create_url('core/misc/icons/bebebe/pencil.svg') . '" alt="' . t('contextual links button') . '" />';
in contextual.module<br/>
s in allowedValuesDescription() from ListIntegerItemComment #73
akalata CreditAttribution: akalata commentedComment #74
woombo CreditAttribution: woombo at ImageX commentedIn my opinion (newbie) this ticket should be reviewed in a much later stage, codebase is being updated every minute and new "br"s are being/will be introduced.
Is there a way to tag or flag this issue to be reviewed in a later stage?
Comment #75
Patrick Storey CreditAttribution: Patrick Storey at Hook 42 commentedI am removing the Novice tag from this issue until we can get an issue summary update. Right now this issue is a little long and convoluted and could really use an update on what the remaining tasks (or roadblocks) are, and then which remaining tasks are novice if not all of them.
I’m using this documentation as a source: https://www.drupal.org/core-mentoring/novice-tasks#avoid
Comment #76
akalata CreditAttribution: akalata commented@woombo the sooner this gets wrapped up and added into core, the sooner it becomes the standard that everyone else needs to match. :)
Comment #79
20th CreditAttribution: 20th commentedPersonally, I would like to see this change make it into the core, so I will try to revive this issue.
Uploading an updated patch. In 2 years Drupal has changed so much that this is more like a new patch than a reroll, there is no point of creating an interdiff.
As already discussed at length in this thread, in this patch I deliberately ignore the filter and editor modules, migrations, fixtures, mail-to-text transformations and security checks in fear of introducing regressions — all of this can be done in the follow-up issues. This patch is focused only on static HTML markup, documentation, JS and tags generation.
I largely agree with @sun comments in #48. One thing I disagree with though is the
<colspan>
tag. It is, in fact, possible to omit its closing tag, so I have included this change as well.Comment #80
20th CreditAttribution: 20th commentedUpdating status for initial patch testing.
Comment #82
20th CreditAttribution: 20th commentedReverting change in
StandardTest
that tests the output offilter
module.Comment #83
20th CreditAttribution: 20th commentedOne of the patched files was deleted, so it does not apply cleanly. Uploading updated patch.
Comment #84
20th CreditAttribution: 20th commentedI cannot find any other self-closing tags in core, other than in filter and editor modules, migrations, fixtures, mail-to-text transformations and security checks. This patch is ready for manual review.
Comment #85
20th CreditAttribution: 20th commentedComment #86
20th CreditAttribution: 20th commentedUpdating patch to include recent additions to the core.
Comment #88
20th CreditAttribution: 20th commentedComment #90
bighappyface CreditAttribution: bighappyface as a volunteer commentedDespite stripping the closing slashes, the PHP function
nl2br
still outputs the closing slashes by default - http://php.net/manual/en/function.nl2br.phpSetting the second parameter for
nl2br
tofalse
will close the loop on comprehensive void elements without the closing slash.Comment #99
longwaveIf #2441811: Upgrade filter system to HTML5 gets it in, it is probably time to revive this and make the rest of core output HTML5 as well.
Comment #104
Dries CreditAttribution: Dries commentedAdded another related issue #3346188: Remove trailing slashes on void elements.
Comment #105
tintoBriefly discussed this with @longwave and @laurii during Drupal Dev Days 2023 and decided to mark #3346188: Remove trailing slashes on void elements as duplicate. I'm copying the work that I did there over to this issue.
It's probably still worth waiting for #2441811: Upgrade filter system to HTML5 to get in first.
Comment #106
Gauravvvv CreditAttribution: Gauravvvv at Axelerant for Drupal India Association commentedI have attached patch for 11.x, please review
Comment #108
longwaveFixed the one remaining test failure.
Comment #109
longwave#105 onwards has lost all the work done in #86 and before. There are still plenty of instances of
<br />
and other void tags in core, perhaps we need to break this out into multiple issues.Comment #110
andypostHope this issue will help to progress with related #1268180: Newline character in HtmlTag causes unwanted whitespace
Comment #111
smustgrave CreditAttribution: smustgrave at Mobomo commented#108 is already a very large patch to review. So think expanding on it would be even more difficult. So think breaking off into smaller tickets make sense. Maybe by tag?
Moving to NW for the follow ups to be created and issue summary to be updated with the new plan (if agreed upon). #108 is a good start so maybe after the follow ups we still merge this?
Comment #112
Eduardo Morales Alberti@smustgrave
Why not open a MR? it is easy to review without open new issues.
Comment #113
quietone CreditAttribution: quietone at PreviousNext commentedBreaking this into smaller issues is not about whether it is a patch or an MR. It is about the scope and patch size. There is a limit to what a reviewer can effectively review and once past that limit, mistakes are made. And we can help avoid those mistakes by splitting this into smaller pieces. There is more information about scope and patch size in the wiki.
I was looking at the patch in #86 and I do agree with smustgrave that doing this by tag is worth pursuing. However, this must be balanced if there are only a few instances of some tags that need changing. It could be sensible to combine some tags together while still keeping the change size small.
Comment #114
Wim LeersI think that thanks to #2441811: Upgrade filter system to HTML5, this now became actually feasible to do!
Comment #115
andypostIn that context would great to tackle #1268180: Newline character in HtmlTag causes unwanted whitespace