Problem/Motivation
When a filter that uses a placeholder, without arguments, is configured in a text format, to run before the filter_htmlcorrector filter, the first filter's placeholder is not replaced on rendering the text. The drupal-filter-placeholder element remains.
A filter might use a placeholder without arguments simply to postpone rendering something that may be expensive to build. I haven't seen any examples in core, but I've come across a custom one before that builds a form in place of a custom token in text.
This is an issue since Drupal 10.2, which started using masterminds/html5 in #2441811: Upgrade filter system to HTML5. I would guess it's still the same in later versions, though I haven't actually tested yet.
Steps to reproduce
- Configure a text format:
- Enable a filter that uses a placeholder without any arguments (I'm not aware of any in core, sorry).
- Enable core's 'Correct faulty and chopped off HTML' filter and ensure it runs after that.
- Make some content that uses that text format and which would cause that first filter's placeholder to be used.
- Expected result: the placeholder is replaced. Actual result: the
drupal-filter-placeholderelement remains.
Proposed resolution
Do not add the arguments attribute to the placeholder markup when it is empty, so that the placeholder does not get altered by the filter_htmlcorrector filter. (This would then match the behavior of \Drupal\Core\Render\PlaceholderGenerator::createPlaceholder().)
Remaining tasks
Review MR.
User interface changes
None.
API changes
None.
Data model changes
None.
Release notes snippet
Issue fork drupal-3454196
Show commands
Start within a Git clone of the project using the version control instructions.
Or, if you do not have SSH keys set up on git.drupalcode.org:
Comments
Comment #2
james.williamsSwitching to target Drupal 11.
Comment #4
james.williamsMR includes a fix and updated tests to demonstrate the issue. The tests without the fix fail as expected (although I'm surprised to see GitLab now shows that with a green tick! But the detailed output shows the failure), and with the fix they pass as expected.
Comment #5
smustgrave commentedSmall super nitpicky change
But MR should be pointed to 11.x vs 11.0.x as 11.x is still the "main" branch.
I see the test-only feature passes when it should fail so tests seem to need some work.
As far as your comment on the MR I also could not find a spot and we don't have a filter sub-maintainer so think it's fine for now.
Comment #6
james.williamsThanks for the review. As I mentioned before, the detailed output in the log of the test-only feature shows there was a test failure. I don't know why the pipeline makes it look like it succeeded!
Comment #7
james.williamsAh @fjgarlin has helped clarify on slack that the tests-only feature showing as passed is a bug in core's test-only script. Please see from the detailed log that the test really does fail!
Comment #10
james.williamsThe fact that the tests-only run can 'pass' is handled in #3409733: Test-only job does not detect failures correctly (which I'm having a go at progressing). I'm including the change from there here for now, as advised by @fjgarlin there.
Comment #11
longwaveThanks for reporting. I was entirely unaware of this in the filter system when I worked on the HTML5 parser upgrade, and so it only works as far as we have test coverage, and we've obviously missing test coverage for this case.
If there are no arguments, would it be better/more correct to not output the arguments attribute at all? ie. we would just have
<drupal-filter-placeholder callback="callback" token="token" />? Then, the HTML5 parser/emitter does not need to special case this at all. But not sure if the placeholder system will need wider work to handle this.Comment #12
longwaveIn PlaceholderGenerator we did update it to optionally output the arguments for HTML5, so I do think we should try the same here:
Comment #13
longwavePushed a change for #11.
Comment #14
james.williamsOh nice idea, thank you! Yes, I'm on board with that, I've tested my case manually too just to check, and it works fine. Combined with the automated test, I trust it's OK to put this to RTBC based on that.
If I were being really nitpicky, I'd suggest we check
Html::escape($arguments) !== '', since it's the escaped version that gets used, but I see we're just doing the same as inPlaceholderGenerator::createPlaceholder(). So if that nitpick even mattered, we could just change both in a follow-up. But I'm not being nitpicky, so ignore that thought ;-)Comment #15
longwaveI think in a followup we could even refactor that code into a static helper method on PlaceholderGenerator, so all placeholders are constructed in a consistent way.
Comment #16
longwaveMistakenly removed the original tag when working on this at Dev Days.
Comment #17
quietone commentedI read the IS, comments and MR. There are no outstanding questions and I had no recommendations to make on the MR. Leaving at RTBC
Added tag for a followup for #15.
Comment #22
larowlanCommitted to 11.x and backported to 11.0.x, 10.4.x and 10.3.x
Thanks folks
Comment #24
james.williamsWoah, thank you!
Comment #25
longwaveOpened #3463038: Add helper method to generate HTML placeholders to simplify the code here.
Comment #27
wim leersWow, quite the edge case! Introduced by yours truly all the way back in #2478483: Introduce placeholders (#lazy_builder) to replace #post_render_cache.