CSSOM rewrites CSS 'page-break-after' as 'break-after' |
|||||||||||||
Issue description
UserAgent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/54.0.2840.71 Safari/537.36
Steps to reproduce the problem:
Repro example:
var s = document.createElement('span');
s.innerHTML = '<div style="page-break-after:always;"></div>'; // Outputs "<div style="page-break-after:always;"></div>"
s.children[0].outerHTML; // Outputs "<div style="page-break-after:always;"></div>"
s.children[0].style.cssText; // Outputs "break-after: page;"
s.children[0].style.pageBreakAfter; // Outputs ""
s.children[0].style.breakAfter; // Outputs "page"
What is the expected behavior?
cssText is unchanged. pageBreakAfter is an available CSS style property
What went wrong?
When parsing HTML with inline CSS, the DOM rewrites the "page-break-after" sytle rule in terms of "break-after".
This is exercised via https://github.com/google/closure-library/blob/master/closure/goog/html/sanitizer/htmlsanitizer.js (see goog.html.sanitizer.HtmlSanitizer.getDomTreeWalker_).
That above example will be re-written as:
<div style="break-after: page;"></div>
This is a problem because com.google.common.html.sanitizer.css.StyleFilter.SAFE_PROPERTIES doesn't allow "break-after" as a style property ("page-break-after" is allowed).
The best "workaround" I can come up for this is after the sanitization takes place:
html = html.replace(/break-after:\s*page;/g, 'page-break-after:always;');
Did this work before? N/A
Does this work in other browsers? N/A
Chrome version: 54.0.2840.71 Channel: stable
OS Version:
Flash Version: Shockwave Flash 23.0 r0
,
Oct 25 2016
This is also true for the other page-break- variants.
,
Oct 25 2016
Here's the full CSSOM rewrite for all possible values of the page-break- variants: "page-break-after: auto;" "break-after: auto;" "page-break-after: always;" "break-after: page;" "page-break-after: avoid;" "break-after: avoid;" "page-break-after: left;" "break-after: left;" "page-break-after: right;" "break-after: right;" "page-break-after: recto;" "" "page-break-after: verso;" "" "page-break-after: inherit;" "break-after: inherit;" "page-break-after: initial;" "break-after: initial;" "page-break-after: unset;" "break-after: unset;" "page-break-before: auto;" "break-before: auto;" "page-break-before: always;" "break-before: page;" "page-break-before: avoid;" "break-before: avoid;" "page-break-before: left;" "break-before: left;" "page-break-before: right;" "break-before: right;" "page-break-before: recto;" "" "page-break-before: verso;" "" "page-break-before: inherit;" "break-before: inherit;" "page-break-before: initial;" "break-before: initial;" "page-break-before: unset;" "break-before: unset;" "page-break-inside: auto;" "break-inside: auto;" "page-break-inside: avoid;" "break-inside: avoid;" "page-break-inside: inherit;" "break-inside: inherit;" "page-break-inside: initial;" "break-inside: initial;" "page-break-inside: unset;" "break-inside: unset;" This was based on sanitizing the following HTML: <div style="page-break-after: auto;"></div> <div style="page-break-after: always;"></div> <div style="page-break-after: avoid;"></div> <div style="page-break-after: left;"></div> <div style="page-break-after: right;"></div> <div style="page-break-after: recto;"></div> <div style="page-break-after: verso;"></div> <div style="page-break-after: inherit;"></div> <div style="page-break-after: initial;"></div> <div style="page-break-after: unset;"></div> <div style="page-break-before: auto;"></div> <div style="page-break-before: always;"></div> <div style="page-break-before: avoid;"></div> <div style="page-break-before: left;"></div> <div style="page-break-before: right;"></div> <div style="page-break-before: recto;"></div> <div style="page-break-before: verso;"></div> <div style="page-break-before: inherit;"></div> <div style="page-break-before: initial;"></div> <div style="page-break-before: unset;"></div> <div style="page-break-inside: auto;"></div> <div style="page-break-inside: avoid;"></div> <div style="page-break-inside: inherit;"></div> <div style="page-break-inside: initial;"></div> <div style="page-break-inside: unset;"></div> Which became: <div style="break-after: auto;"></div> <div style="break-after: page;"></div> <div style="break-after: avoid;"></div> <div style="break-after: left;"></div> <div style="break-after: right;"></div> <div></div> <div></div> <div style="break-after: inherit;"></div> <div style="break-after: initial;"></div> <div style="break-after: unset;"></div> <div style="break-before: auto;"></div> <div style="break-before: page;"></div> <div style="break-before: avoid;"></div> <div style="break-before: left;"></div> <div style="break-before: right;"></div> <div></div> <div></div> <div style="break-before: inherit;"></div> <div style="break-before: initial;"></div> <div style="break-before: unset;"></div> <div style="break-inside: auto;"></div> <div style="break-inside: avoid;"></div> <div style="break-inside: inherit;"></div> <div style="break-inside: initial;"></div> <div style="break-inside: unset;"></div>
,
Oct 25 2016
Would you mind providing a sample html page for ease of triaging?
,
Oct 25 2016
AFAICT this is mostly WAI since page-* are aliases, except that e.style.pageBreakAfter shouldn't be empty. Probably the StylePropertySerializer needs to be updated to support these. https://drafts.csswg.org/css-break/#page-break-properties
,
Oct 26 2016
tflo@:
> This is a problem because com.google.common.html.sanitizer.css.StyleFilter.SAFE_PROPERTIES doesn't allow "break-after" as a style property ("page-break-after" is allowed).
I think the best way forward is to fix the sanitizer. The "break-after" property is already in Candidate Recommendation, I don't see any good reasons to reject the use of it.
https://www.w3.org/TR/css-break-3/
Did you file a bug to the sanitizer?
,
Oct 26 2016
tflo@: Could you please provide us the sample html file for further triaging the issue. Thanks.
,
Oct 26 2016
I'm not on the same time as you guys :) jmukthavaram@chromium.org, ligimole@chromium.org: Here's a test bed. It demonstrates the actual CSS style, the reported cssText, and which style properties are set. https://jsfiddle.net/b1dnzohp/ https://fiddle.jshell.net/b1dnzohp/show/light/ (Result view) kojii@chromium.org, timloh@chromium.org: I actually submitted a patch to allow the break-* properties but I reverted it as the browser compatability for those properties are so low: https://developer.mozilla.org/en-US/docs/Web/CSS/break-after#Browser_compatibility https://developer.mozilla.org/en-US/docs/Web/CSS/break-before#Browser_compatibility https://developer.mozilla.org/en-US/docs/Web/CSS/break-inside#Browser_compatibility Perhaps those compatability tables need to be updated?
,
Oct 26 2016
Some more links: FireFox results for comparison (HTML result only): https://fiddle.jshell.net/z8658f54/1/show/light/ Updated test that works on FireFox: https://fiddle.jshell.net/b1dnzohp/1/show/light/ I would say that FireFox's results are more "as expected" than Chrome's.
,
Nov 1 2016
Able to reproduce the issue on windows 7,Mac 10.11.4,Ubuntu 14.04 using chrome reported version #54.0.2840.71 & latest canary #56.0.2906.0. This is a non regression as it is observed from M52 to latest canary & same feature not available from M45,M50 & M51 old builds. Hence, marking it as Untriaged to get more inputs from dev team. Thanks,
,
Nov 1 2016
,
Nov 1 2016
,
Nov 2 2016
,
Dec 27 2016
I have also observed this behavior, but in a different context.
To reproduce:
var s = document.createElement('span');
s.style.pageBreakAfter = 'always';
console.log('s.style.pageBreakAfter: ', s.style.pageBreakAfter);
console.log('s.style.breakAfter: ', s.style.breakAfter);
Here is a link to a codepen:
http://codepen.io/aljachimiak/pen/PbrRao?editors=0011
Open in Chrome and you'll find that s.pageBreakAfter is an empty string.
Open in FireFox and you'll find that s.pageBreakAfter is 'always'.
The problem here is then when I explicitly set a property, I expect it to be set.
I kind of like that the equivalent property is being set for future spec support.
My opinion is that the property that is explicitly set in js, should ALWAYS be set. It's okay to set another equivalent property.
My use case here is that we are sending the rendered html to a server side printer that doesn't support `break-before` yet.
Note:
If you've got jQuery on your page this actually worke:
$(elem).css('page-break-before', 'always');
Thanks for your time and attention!
- Al
,
Dec 27 2016
> Note:
> If you've got jQuery on your page this actually works:
> $(elem).css('page-break-before', 'always');
Nope - I was not in Chrome when I tried this. Sorry for the false hope.
,
Feb 5 2017
,
Feb 13 2017
,
Oct 31 2017
,
Dec 6 2017
,
Mar 12 2018
The following revision refers to this bug: https://chromium.googlesource.com/chromium/src.git/+/da3d4e26aef179e83366f6efafb66e54676066ed commit da3d4e26aef179e83366f6efafb66e54676066ed Author: Chris Nardi <cnardi@chromium.org> Date: Mon Mar 12 11:54:42 2018 [cssom] Allow accessing page-break-* properties through style We internally represent all page-break-* properties as shorthands for break-* properties, per the spec [1]. However, we do not check this on serialization, meaning style.pageBreak* is always "". Add logic into StylePropertySerializer to check for the page break shorthands. [1]: https://drafts.csswg.org/css-break/#page-break-properties Bug: 659297 Change-Id: Id8fc71f7f279d474f39ce37fbd3ad7791e1b40c7 Reviewed-on: https://chromium-review.googlesource.com/957836 Reviewed-by: Rune Lillesveen <futhark@chromium.org> Commit-Queue: Chris Nardi <cnardi@chromium.org> Cr-Commit-Position: refs/heads/master@{#542463} [modify] https://crrev.com/da3d4e26aef179e83366f6efafb66e54676066ed/third_party/WebKit/LayoutTests/external/wpt/css/cssom/serialize-values-expected.txt [modify] https://crrev.com/da3d4e26aef179e83366f6efafb66e54676066ed/third_party/WebKit/Source/core/css/StylePropertySerializer.cpp [modify] https://crrev.com/da3d4e26aef179e83366f6efafb66e54676066ed/third_party/WebKit/Source/core/css/StylePropertySerializer.h
,
Mar 12 2018
I think this is fixed now; getting pageBreak* properties via style will give you the correct answer. cssText still rewrites page-break-* to break-*, but I think this follows the spec regarding the serialization of shorthands. |
|||||||||||||
►
Sign in to add a comment |
|||||||||||||
Comment 1 by tkent@chromium.org
, Oct 25 2016Summary: CSSOM rewrites CSS 'page-break-after' as 'break-after' (was: DOM rewrites CSS 'page-break-after' as 'break-after')