In Drupal 7 you could inject arbitrary markup into the html head, eg:
drupal_add_html_head(array(
'#type' => 'markup',
'#markup' => 'anything I like',
), 'my_key');
This is necessary when, eg. you're getting html snippets from 3rd party systems that need to be placed into the html head.
In Drupal 8, it appears the limitations of the Drupal\Core\Page\HtmlPage
object means that only meta elements and link elements can be injected into the html head. All other renderable arrays passed into drupal_add_html_head()
silently fail.
IMO, there needs to be way to inject arbitrary html in to the html head.
Comment | File | Size | Author |
---|---|---|---|
#31 | interdiff.txt | 959 bytes | kgoel |
#31 | html-head-2296951-31.patch | 6.07 KB | kgoel |
#28 | interdiff.txt | 4.49 KB | kgoel |
#28 | html-head-2296951-28.patch | 7 KB | kgoel |
#26 | html-head-2296951-26.patch | 6.47 KB | kgoel |
Comments
Comment #1
dawehnerIn case you need an arbitrary HTML noone stops you to expand the HeadElement class to implement your own and add it onto the page object, see https://api.drupal.org/api/drupal/core!lib!Drupal!Core!Page!HeadElement....
Comment #2
torrance123 CreditAttribution: torrance123 commented@dawehner Nope, that doesn't work. The
HtmlPage::getHead()
method is hardcoded to only print meta and link elements:return implode("\n", $this->getMetaElements()) . implode("\n", $this->getLinkElements());
And in turn, each of the setter methods for
addMetaElement()
andaddLinkElement
are typed to only accept aMetaElement
and aLinkElement
object respectively.Thus, if I subclass
HeadElement
there's still no way to get my custom element into the head of theHtmlPage
object.Comment #3
dawehnerOkay you are right, but I don't see why we cannot add support for it.
Comment #4
dawehnerAre you sure you want to include aribtrary stuff? I cannot see why this should be allowed on https://developer.mozilla.org/en-US/docs/Web/HTML/Element/head
Comment #5
torrance123 CreditAttribution: torrance123 commentedThe use case I'm dealing with is that I'm given valid
<script>
elements from a 3rd party system (including the enclosing<script>
tags). So either I need to perform some fairly robust parsing of the html snippets I'm given, separate out the<script>
elements (and possibly<link>
elements too) and strip the enclosing tags before passing them to the HtmlPage element; OR else simply be allowed to add full html snippets to the html head.Comment #6
Crell CreditAttribution: Crell commentedMy concern is that we're pushing very hard to have properly structured domain objects now rather than a weird and impossible to document amalgam of arrays, strings, and bubblegum. The Twig folks are also pushing to even have strings wrapped up in objects: #1825952: Turn on twig autoescape by default. Allowing a method to add an arbitrary HeadElement class or subclass, and making sure that those are also then rendered and returned, seems reasonable to me.
Allowing arbitrary unfiltered strings to be injected into the HTML head sounds very worrisome and very dangerous. It would also be completely bypassing all of Drupal's automation around such things, making this issue related to #2298551: Documentation updates adding/adjusting inline/external JS in themes.
What's the use case for "paste this arbitrary snippet of HTML" that you would want to be doing at a module HtmlPage domain object level, rather than just opening up html.html.twig and pasting it in there?
Comment #7
Crell CreditAttribution: Crell commentedComment #8
torrance123 CreditAttribution: torrance123 commented@Crell
My specific use case is that I'm integrating CiviCRM into Drupal 8. I don't know ahead of time what code I'm injecting into the head, so using html.html.twig doesn't work.
Of course, the other avenue I could go down is lodge a bug with CiviCRM and ask them to output their js in a more structured way.
That would be fine, but really just opens the backdoor to allowing me to get whatever I want into the head so I'm not sure if it actually addresses your concerns about properly structured domain objects.
Comment #9
Crell CreditAttribution: Crell commentedWell, a generic HeadElement would at least give us pre-parsed data that we can safely escape; much like the SQL query builders give us structured data that we know how to stringify and escape without relying on regexes. It's entirely arbitrary strings that I am scared of.
That said, the number of legal HTML head tags is small and finite. Could we just add any missing element types we have and call it a day?
Comment #10
dawehnerStarted some work on it.
@crell See tell in IRC
Comment #11
Crell CreditAttribution: Crell commentedThis isn't in the interface yet, it looks like. And shouldn't it actually do something? :-)
I think this one is unnecessary as we already have a method for the title on HtmlFragment/HtmlPage directly.
Comment #12
dawehnerThanks for the review!!
Yeah right. I think the getElements method should return all HEAD elements.
Comment #14
dawehnerThis time with much less failures.
Comment #16
dawehnerSome less test failures.
Comment #17
Crell CreditAttribution: Crell commentednoscript tags are supposed to wrap other tags. Making it its own tag seems problematic. It's also unnecessary, as HeadElement already has a noscript flag on it. That makes a stand-alone class for it unnecessary.
Except the implementation is not returning "all other HEAD elements". It's returning all HEAD elements, period. I'm OK with that, but the comment should reflect it.
I think other than those two points this is good to go. Thanks, dawehner!
Comment #18
Crell CreditAttribution: Crell commentedComment #19
dawehner@crell
Yeah right, this is just a leftover from the initial implementation.
One thing I am not really sure how to solve is, how we can ensure that passing by reference works for both link elements but also all elements. You could
store just a plain array of elements for getElements() but then the filtering for getLinkElements() would destroy it again. What about just supporting removing for getElements()?
Comment #20
Crell CreditAttribution: Crell commentedHm. Well the objects pass by handle. That gives two possibilities:
1) Use collection object rather than an array, so it always returns "by reference" (scare quotes intended).
2) Have getElements() create a new array of all objects that aggregates everything from the keyed array, then return that by reference. You'd still get a handle to the original objects, just not through the original array.
The better question, though, is what the use case is for getElements() returning by reference. For CSS and JS it would be to allow alters, essentially, specifically for #2334225: Move CSS/JS preprocessing to a View listener. But is there a use case for by-reference of all objects? I'm not clear that there is. For getting all objects period, the use case is the page template. Although I don't know if themers would even want that rather than doing them separately. :-)
Comment #21
dawehnerWell, at least at the moment it seemed to be common to reorder to metatags itself, why should allow that for every HEAD element?
Comment #22
Crell CreditAttribution: Crell commentedWhat value is there to reordering metatags? Content type and encoding http-equivs should come first for browser parsing, but beyond that who cares? Does it impact anything?
More to the point, I'm leaning toward leaving it out at this point and getting the rest of this in. It's already a step forward and I don't want to hold up the issue on figuring out where we may want to possibly do that kind of fancy-pants reordering, especially since that opens up all kinds of other sticky questions.
Comment #23
dawehnerWell, if we don't add support here, people will complain as metatags do have support for it already.
Comment #24
joelpittetI'm quite sure but I don't thing meta tags ever need to be sorted. (Will grep contrib in d7 to be sure).
Questions that came to mind:
Is this needed? It's not used in the patch. I'm guessing this is the tag and would be in the 'other', category.
Likely it is needed, just asking because if so, I may want to check other 'HeadElement' that may need to be added.
Can we move this back to #type=>html_tag or can we remove html_tag, they are competing for the exact same markup.
Comment #25
Crell CreditAttribution: Crell commentedI am fine with removing #type=>html_tag.
Comment #26
kgoel CreditAttribution: kgoel commentedComment #27
Crell CreditAttribution: Crell commentedThese variables are not defined...? They should be default values for the command element (I didn't even know that existed), possibly overridden by the constructor params.
This is now being used as the only elements property. Which means
1) The description is wrong.
2) The @var is wrong, since it's an array of arrays of head elements.
3) We should document that structure.
4) It should be called $headElements to make it clear that it's not arbitrary HTML elements.
5) We should remove $metatags and $links.
Comment #28
kgoel CreditAttribution: kgoel commentedComment #29
Crell CreditAttribution: Crell commentedTarget is not a property of Command. The optional parameters should be label and icon, I wager, with defaults of '', and then specify those in the attributes array.
(Also, let's go ahead and use [ ] here instead of array(), just to be pedantic. :-) )
Comment #30
dawehnerThis is fine for me as it solves the problem people head with it. Would be great though of metatags module would be converted already.
Comment #31
kgoel CreditAttribution: kgoel commentedSomehow I missed this comment on https://developer.mozilla.org/en-US/docs/Web/HTML/Element/command regarding command element -
This feature is obsolete. Although it may still work in some browsers, its use is discouraged since it could be removed at any time. Try to avoid using it.
I have removed CommandElement.php so it addresses the concern in https://www.drupal.org/node/2296951#comment-9196753.
Comment #32
fgmLooks good to me.
Comment #33
Crell CreditAttribution: Crell commentedThanks, kgoel!
Comment #34
alexpottThe issue summary is not update to date with the current patch.
This functionality is untested.
The implements don't match and the docs don't mention the elements are returned by ref.
Also we probably have some CRs to update after this. We need to document that we no longer support adding arbitrary stuff to HEAD
Comment #35
Wim LeersDue to #2350943: [Meta] Untangle Drupal 8 page rendering, this is effectively a won't-fix now, I'm afraid.