Web Inspector: ER: Copy Node as HTML with Computed Style It'd be super useful to have a variant of the "Copy as HTML" feature that dumped each element's computed style properties into the style attribute of each tag. It'd be harder to read the generated HTML, but easier to debug and create test cases.
<rdar://problem/27809183>
This would be very useful, indeed. I'd use it myself, I make test cases too.
Devin, this seems right up your alley. Feel free to assign it to yourself if you want to work on this.
Do we want to dump the computed style of each element or just the selected/context-menu element? Also, do we want to display all the computed properties, or just the ones that have been specified/inherited?
(In reply to comment #4) > Do we want to dump the computed style of each element or just the > selected/context-menu element? Selected/context-menu element and all its descendants. I imagine it can blow up very easily, but I'd rather deal with this later. > Also, do we want to display all the computed > properties, or just the ones that have been specified/inherited? The ones that have been specified/inherited.
Created attachment 286554 [details] Patch I strayed away from the description slightly due to the fact that we are unable to reliably fetch the computed style of each node (including children) in a synchronous way (at least with the current implementation). Given that there is already a "Copy as HTML", I thought that it made more sense to just add "Copy Computed Style" that dumps a newline-separated list of the set/inherited CSS properties to the clipboard.
Attachment 286554 [details] did not pass style-queue: ERROR: Source/WebInspectorUI/UserInterface/Views/DOMTreeElement.js:711: Line contains single-quote character. [js/syntax] [5] ERROR: Source/WebInspectorUI/UserInterface/Views/DOMTreeElement.js:712: Line contains single-quote character. [js/syntax] [5] Total errors found: 2 in 2 files If any of these errors are false positives, please file a bug against check-webkit-style.
Created attachment 286555 [details] Patch
(In reply to comment #6) > Created attachment 286554 [details] > Patch > > I strayed away from the description slightly due to the fact that we are > unable to reliably fetch the computed style of each node (including > children) in a synchronous way (at least with the current implementation). > Given that there is already a "Copy as HTML", I thought that it made more > sense to just add "Copy Computed Style" that dumps a newline-separated list > of the set/inherited CSS properties to the clipboard. I don't think this is very helpful. Getting computed styled of all descendants is a harder task, but that's what would make this feature useful.
(In reply to comment #9) > I don't think this is very helpful. Getting computed styled of all > descendants is a harder task, but that's what would make this feature useful. I would agree that getting the computed style of all descendants would be more useful, but the issue is with fetching those styles. Since we lazy-load instances of DOMNodeStyles when the user selects an element in the DOM tree, if they haven't selected a descendent node and try to dump the computed styles via the context menu item on a parent, it will just show an empty CSSStyleDeclaration (no properties). I am pretty sure that I could include a WrappedPromise in some of the functions (specifically DOMNodeStyles.prototype.refresh) that would let us tie into the fetch when it completes, but this has the possibility of lagging and may add items to the clipboard in a very asynchronous manner. If we are OK with that, then I can do this, but I am worried about situations where the user attempts to click the context menu item on <body> and has the entire DOM tree copied to the clipboard after a few seconds since it has to perform so many calls to generate the computed style of each descendant.
Comment on attachment 286555 [details] Patch r- while we discuss implementing the more useful feature.
(In reply to comment #10) > (In reply to comment #9) > > I don't think this is very helpful. Getting computed styled of all > > descendants is a harder task, but that's what would make this feature useful. > > I would agree that getting the computed style of all descendants would be > more useful, but the issue is with fetching those styles. Since we > lazy-load instances of DOMNodeStyles when the user selects an element in the > DOM tree, if they haven't selected a descendent node and try to dump the > computed styles via the context menu item on a parent, it will just show an > empty CSSStyleDeclaration (no properties). I think the more useful feature is what users will want and expect. The question then is how do we implement it? You've alluded to how the frontend could do this, laboriously, by requesting information about every node. Which breaks down for large documents. But we haven't explored other options. I think this could be done in the backend. Take for example, this test page, and the user wants to copy the styles for the <body> element: > index.html: > > <!DOCTYPE html> > <html> > <head> > <link rel="stylesheet" href="styles1.css"> > <link rel="stylesheet" href="styles2.css"> > <script> > window.addEventListener("load", function() { > document.getElementById("red").style.color = "red"; > }); > </script> > </head> > <body> > <div class="foo"> > <p style="color:green">Green</p> > <p>Blue</p> > <p id="red">Red</p> > </div> > </body> > </html> > > styles1.css: > > .foo { color: blue; text-decoration: underline; } > .foo:hover { color: black; } > > styles2.css: > > body { margin: 0; padding: 0; } There are a few approaches I can think of. 1. Iterate all nodes from the target, producing inline style for non-inherited overridden styles: <body style="margin: 0; padding: 0"> <div class="foo" style="color: blue"> <p style="color: green; text-decoration: underline">Green</p> <p style="color: blue; text-decoration: underline">Blue</p> <p id="red" style="color: red; text-decoration: underline">Red</p> </div> </body> 2. Collect the stylesheets into an inline <style> alongside the nodes iterated from target with their inline styles that don't come from a stylesheet. <style> .foo { color: blue; text-decoration: underline; } .foo:hover { color: black; } body { margin: 0; padding: 0; } </style> <body> <div class="foo"> <p style="color: green">Green</p> <p>Blue</p> <p id="red" style="color: red">Red</p> </div> </body> Forgive any subtle typos or logic errors I may have made, I typed this all into a bugzilla comment without testing. There are pro and cons of both approaches as I see it: 1. Pure Inline Styles - standalone, easy to copy/paste - verbose, numerous styles may be repeated over and over again - a pure snapshot, missing pseudo states (like :hover) - can provide developer with surprising discovery ("oh this style is on a lot of elements, why?") 2. Stylesheet + Inline Styles - can contain "unused styles" - but that can be pseudo states (like :hover) - total verbose, copying entire stylesheets can be wasteful - more readable DOM, no unnecessary inline style clutter - less copy/pasteable, can be a good thing I rather like (2) because of the fact it can handle pseudo classes like :hover. But I'd like to hear what other users think.
I would on the whole err on the side of (1) because it means that you get a self-contained bunch of HTML, rather than something that's only acceptable when you're putting it directly under the root element (given style elements need to be the child of the head element). My current use-case is wanting to copy a small snippet of Twitter.com's HTML+CSS to see if simply extracting a small part is sufficient to reproduce a bug. Having everything directly tied to the elements makes it easier to hand-edit without having to figure out what classes do what.