Bug 178835

Summary: Web Inspector: Styles: format style declarations after editing
Product: WebKit Reporter: Nikita Vasilyev <nvasilyev>
Component: Web InspectorAssignee: Nikita Vasilyev <nvasilyev>
Status: RESOLVED FIXED    
Severity: Normal CC: eric.carlson, ews-watchlist, glenn, hi, inspector-bugzilla-changes, jer.noble, pangle, philipj, rcaliman, sergio, webkit-bug-importer
Priority: P2 Keywords: InRadar
Version: WebKit Nightly Build   
Hardware: All   
OS: All   
See Also: https://bugs.webkit.org/show_bug.cgi?id=178990
Bug Depends on:    
Bug Blocks: 225538, 227411    
Attachments:
Description Flags
Patch
none
Patch
none
Patch
none
Patch
none
Patch
none
Patch
none
Patch
none
Patch none

Nikita Vasilyev
Reported 2017-10-25 15:40:47 PDT
Currently, a newly added property get appended without any indentation or line-breaks. Adding "color: red" to: body { font-family: sans-serif; } Currently results in: body { font-family: sans-serif;color: red; } Expected (when the indentation in setting is set to 4 spaces): body { font-family: sans-serif; color: red; }
Attachments
Patch (19.71 KB, patch)
2021-05-19 11:11 PDT, Nikita Vasilyev
no flags
Patch (19.54 KB, patch)
2021-05-19 11:30 PDT, Nikita Vasilyev
no flags
Patch (20.59 KB, patch)
2021-06-02 13:06 PDT, Nikita Vasilyev
no flags
Patch (24.52 KB, patch)
2021-06-02 17:25 PDT, Nikita Vasilyev
no flags
Patch (43.79 KB, patch)
2021-07-15 10:00 PDT, Nikita Vasilyev
no flags
Patch (44.27 KB, patch)
2021-07-28 14:56 PDT, Nikita Vasilyev
no flags
Patch (45.13 KB, patch)
2021-10-06 08:09 PDT, Razvan Caliman
no flags
Patch (45.15 KB, patch)
2021-10-07 09:43 PDT, Razvan Caliman
no flags
Radar WebKit Bug Importer
Comment 1 2017-10-25 15:41:04 PDT
Nikita Vasilyev
Comment 2 2021-05-19 11:11:04 PDT Comment hidden (obsolete)
Nikita Vasilyev
Comment 3 2021-05-19 11:30:23 PDT
Devin Rousso
Comment 4 2021-05-19 15:08:39 PDT
Comment on attachment 429078 [details] Patch View in context: https://bugs.webkit.org/attachment.cgi?id=429078&action=review So does this mean that if I'm editing a minified CSS style sheet resource in the Styles panel then my changes will result in a bunch of pretty-printed text appearing in the middle of the minified resource? I'm not sure if that's what we want to do. Maybe we should only do this if we believe that the style sheet resource already is pretty-printed (e.g. using `isTextLikelyMinified`)? > Source/WebInspectorUI/UserInterface/Models/CSSStyleDeclaration.js:514 > + generateFormattedText() Why not use/modify `generateCSSRuleString`? Like have an `options = {}` that controls what things are added so that we don't have repeated work (e.g. `includeGroupings`, `allowInline`, etc.).
Nikita Vasilyev
Comment 5 2021-05-20 10:04:55 PDT
Comment on attachment 429078 [details] Patch View in context: https://bugs.webkit.org/attachment.cgi?id=429078&action=review >> Source/WebInspectorUI/UserInterface/Models/CSSStyleDeclaration.js:514 >> + generateFormattedText() > > Why not use/modify `generateCSSRuleString`? Like have an `options = {}` that controls what things are added so that we don't have repeated work (e.g. `includeGroupings`, `allowInline`, etc.). Yes, I can merge the two. Caveats: - generateCSSRuleString generates a CSS rule, so it includes `cssSelector { cssDeclaration }`. It should probably make more sense to have this method on CSSRule, not CSSStyleDeclaration, but I digress. - indentation is slightly different (e.g. for the closing "}")
Nikita Vasilyev
Comment 6 2021-05-20 10:18:57 PDT
(In reply to Devin Rousso from comment #4) > Comment on attachment 429078 [details] > Patch > > View in context: > https://bugs.webkit.org/attachment.cgi?id=429078&action=review > > So does this mean that if I'm editing a minified CSS style sheet resource in > the Styles panel then my changes will result in a bunch of pretty-printed > text appearing in the middle of the minified resource? I'm not sure if > that's what we want to do. ... Yes. Why is it bad? Is it for saving the resource? It is certainly easier to read and edit non-minified resource.
Nikita Vasilyev
Comment 7 2021-06-02 13:06:41 PDT
Nikita Vasilyev
Comment 8 2021-06-02 13:11:31 PDT
(In reply to Devin Rousso from comment #4) > > Source/WebInspectorUI/UserInterface/Models/CSSStyleDeclaration.js:514 > > + generateFormattedText() > > Why not use/modify `generateCSSRuleString`? Like have an `options = {}` > that controls what things are added so that we don't have repeated work > (e.g. `includeGroupings`, `allowInline`, etc.). I did that. The options are different though. (In reply to Nikita Vasilyev from comment #5) > - generateCSSRuleString generates a CSS rule, so it includes `cssSelector { > cssDeclaration }`. It should probably make more sense to have this method on > CSSRule, not CSSStyleDeclaration, but I digress. I tried to refactor this and move generateCSSRuleString method to CSSRule. Then realized that it also need to work for inline styles. It makes sense to me to keep it as-is now.
Nikita Vasilyev
Comment 9 2021-06-02 13:16:59 PDT
(In reply to Nikita Vasilyev from comment #8) > (In reply to Devin Rousso from comment #4) > > > Source/WebInspectorUI/UserInterface/Models/CSSStyleDeclaration.js:514 > > > + generateFormattedText() > > > > Why not use/modify `generateCSSRuleString`? Like have an `options = {}` > > that controls what things are added so that we don't have repeated work > > (e.g. `includeGroupings`, `allowInline`, etc.). > > I did that. The options are different though. To amend my message: I kept the two methods separate, still. I think generateCSSRuleString should generate, well, a CSS rule. It shouldn't generate a style declaration (e.g. a list of CSS properties).
Nikita Vasilyev
Comment 10 2021-06-02 17:25:34 PDT
Devin Rousso
Comment 11 2021-06-04 16:08:20 PDT
Comment on attachment 430422 [details] Patch View in context: https://bugs.webkit.org/attachment.cgi?id=430422&action=review > LayoutTests/inspector/css/generateFormattedText.htmlLayoutTests/inspector/css/generateCSSRuleString.html:22 > + InspectorTest.log(nodeStyles.inlineStyle.generateFormattedText({includeGroupings: true, forceMultiline: true})); Can we add some tests for the other permutations (e.g. `{includeGroupings: true}`)? > Source/WebInspectorUI/ChangeLog:18 > + Introduce `_pendingText` property. It's only set when pasting CSS property text into the CSS property name field. Can you explain why this is needed? Why can't we just `this._text = text;`? > Source/WebInspectorUI/UserInterface/Models/CSSProperty.js:190 > this._text = newText; Do we need to do this before calling `_updateOwnerStyleText`? > Source/WebInspectorUI/UserInterface/Models/CSSProperty.js:-515 > - this._styleSheetTextRange = this._styleSheetTextRange.cloneAndModify(0, 0, lineDelta, columnDelta); Can we verify that the `_styleSheetTextRange` gets updated (and to the right value) after `this._ownerStyle.text = ...`? > Source/WebInspectorUI/UserInterface/Models/CSSStyleDeclaration.js:503 > + styleText += indentString.repeat(groupingsCount) + this.selectorText + " {"; We should probably have a separate option for `includeSelector` since it's not a CSS grouping (or rename `includeGrouping` to also mention "selector" or something). I would also add a `console.assert(!options.includeGroupings || options.includeSelector, options)` too as it doesn't make sense to show CSS groupings without the selector.
Nikita Vasilyev
Comment 12 2021-07-15 10:00:38 PDT
Nikita Vasilyev
Comment 13 2021-07-15 10:06:02 PDT
Comment on attachment 430422 [details] Patch View in context: https://bugs.webkit.org/attachment.cgi?id=430422&action=review >> Source/WebInspectorUI/ChangeLog:18 >> + Introduce `_pendingText` property. It's only set when pasting CSS property text into the CSS property name field. > > Can you explain why this is needed? Why can't we just `this._text = text;`? When pasting CSS, we need to save that exact text. We don't want to save formatted text based on the name/value — they are outdated now. In my latest patch, I replaced `_pendingText` with `_isTextPendingSave`, which is a boolean flag.
Devin Rousso
Comment 14 2021-07-19 12:13:28 PDT
Comment on attachment 433595 [details] Patch View in context: https://bugs.webkit.org/attachment.cgi?id=433595&action=review > LayoutTests/ChangeLog:11 > + - Add a basic test unsuring styleSheetTextRange updates correctly from the backend. s/unsuring/ensuring > LayoutTests/inspector/css/generateFormattedText-expected.txt:12 > + I don't think there should be a newline at the start when we're not including groupings/selectors > LayoutTests/inspector/css/generateFormattedText-expected.txt:13 > + a: 1; It's odd that this is indented when there's no groupings/selectors 🤔 > LayoutTests/inspector/css/generateFormattedText-expected.txt:32 > + ditto (:12) > LayoutTests/inspector/css/generateFormattedText-expected.txt:33 > + a: 1; ditto (:13) > LayoutTests/inspector/css/generateFormattedText-expected.txt:53 > +@media only screen and (min-width: 0px) {@media only screen and (min-height: 0px) {body > div#test-node {a: 1; b: 2; c: 3;}}} It's a bit odd that we add spaces between `#test-node` and `{` or between CSS properties, but not between `{` and `@media`/`body` or before/after the first/last CSS property. Maybe we should be a bit more liberal with whitespace? > LayoutTests/inspector/css/generateFormattedText-expected.txt:60 > + ditto (:12) > LayoutTests/inspector/css/generateFormattedText-expected.txt:61 > + a: 1; ditto (:13) > LayoutTests/inspector/css/generateFormattedText-expected.txt:127 > +@media only screen and (min-width: 0px) {@media only screen and (min-height: 0px) {body > div#test-node {a: 1; /* b: 2; */ c: 3;}}} ditto (:53) > LayoutTests/inspector/css/generateFormattedText-expected.txt:134 > + ditto (:12) > LayoutTests/inspector/css/generateFormattedText-expected.txt:135 > + a: 1; ditto (:13) > LayoutTests/inspector/css/generateFormattedText.html:16 > + let suite = InspectorTest.createSyncSuite("CSS.generateCSSRuleString"); NIT: this should really be `"WI.CSSStyelDeclaration.prototype.generateFormattedText"` (and ditto below too) > LayoutTests/inspector/css/modify-css-property.html:44 > + styleDeclaration.awaitEvent(WI.CSSStyleDeclaration.Event.PropertiesChanged).then((event) => { Can you use `singleFireEventListener` to make sure that the extra microtask of the `Promise` isn't influencing the test result? > LayoutTests/inspector/css/modify-css-property.html:48 > + let relativeRange = fontProperty.styleSheetTextRange.relativeTo(fontProperty.ownerStyle.styleSheetTextRange.startLine, fontProperty.ownerStyle.styleSheetTextRange.startOffset); > + relativeRange.resolveOffsets(fontProperty.ownerStyle.text); > + let propertyText = fontProperty.ownerStyle.text.slice(relativeRange.startOffset, relativeRange.endOffset); Is this logic actually found in Web Inspector? If yes, why can't we test that code instead of this? If not, why is this needed? > Source/WebInspectorUI/UserInterface/Models/CSSProperty.js:214 > + this._isTextPendingSave = true; Please add this variable to the constructor to avoid adding a new JSC structure. NIT: I think this needs a clearer name. Maybe something like `_isUpdatingText` or `_isWaitingForResponseAfterChangingText`? > Source/WebInspectorUI/UserInterface/Models/CSSProperty.js:222 > + return this._text.trim(); Instead of `trim()` each time this is called, can we `trim()` once inside `set text` instead? > Source/WebInspectorUI/UserInterface/Models/CSSProperty.js:507 > + this._updateOwnerStyleText(); Should this also be wrapped with `_isTextPendingSave`? > Source/WebInspectorUI/UserInterface/Models/CSSProperty.js:516 > + let multiline = this._ownerStyle.type === WI.CSSStyleDeclaration.Type.Rule NIT: I'd inline this
Nikita Vasilyev
Comment 15 2021-07-19 12:43:31 PDT
Comment on attachment 433595 [details] Patch View in context: https://bugs.webkit.org/attachment.cgi?id=433595&action=review >> LayoutTests/inspector/css/generateFormattedText-expected.txt:13 >> + a: 1; > > It's odd that this is indented when there's no groupings/selectors 🤔 It does indeed look odd in the test, but that's what we want to do to save formatted text — we need to send style declarations, which is everything inside of `selectior {...}`, but no selectors or groupings. >> LayoutTests/inspector/css/generateFormattedText-expected.txt:53 >> +@media only screen and (min-width: 0px) {@media only screen and (min-height: 0px) {body > div#test-node {a: 1; b: 2; c: 3;}}} > > It's a bit odd that we add spaces between `#test-node` and `{` or between CSS properties, but not between `{` and `@media`/`body` or before/after the first/last CSS property. > > Maybe we should be a bit more liberal with whitespace? This is not a real-world scenario. I'm testing dead code, essentially. includeGroupingsAndSelectors is always used with `multiline` (for Copy Rule context menu). >> LayoutTests/inspector/css/generateFormattedText.html:16 >> + let suite = InspectorTest.createSyncSuite("CSS.generateCSSRuleString"); > > NIT: this should really be `"WI.CSSStyelDeclaration.prototype.generateFormattedText"` (and ditto below too) Oops, thanks. >> LayoutTests/inspector/css/modify-css-property.html:48 >> + let propertyText = fontProperty.ownerStyle.text.slice(relativeRange.startOffset, relativeRange.endOffset); > > Is this logic actually found in Web Inspector? If yes, why can't we test that code instead of this? If not, why is this needed? No, I don't think it is. I'm testing that styleSheetTextRange is correctly updated from the backend. Initially, I used expectEqual on styleSheetTextRange objects themselves, but it was too cryptic and hard to understand when the test was failing. >> Source/WebInspectorUI/UserInterface/Models/CSSProperty.js:214 >> + this._isTextPendingSave = true; > > Please add this variable to the constructor to avoid adding a new JSC structure. > > NIT: I think this needs a clearer name. Maybe something like `_isUpdatingText` or `_isWaitingForResponseAfterChangingText`? `_isUpdatingText` sounds good to me. >> Source/WebInspectorUI/UserInterface/Models/CSSProperty.js:222 >> + return this._text.trim(); > > Instead of `trim()` each time this is called, can we `trim()` once inside `set text` instead? Either way it should only get called once. But sounds good. >> Source/WebInspectorUI/UserInterface/Models/CSSProperty.js:507 >> + this._updateOwnerStyleText(); > > Should this also be wrapped with `_isTextPendingSave`? Like `if (this._isTextPendingSave) this._updateOwnerStyleText()` ? No, it shouldn't because `_isTextPendingSave` is false when we edit name/value. It's only true pasting CSS and commenting/uncommenting (the latter could be rewritten to not use this._text directly, actually, but I digress).
Nikita Vasilyev
Comment 16 2021-07-28 14:47:41 PDT
Comment on attachment 433595 [details] Patch View in context: https://bugs.webkit.org/attachment.cgi?id=433595&action=review >>> LayoutTests/inspector/css/generateFormattedText-expected.txt:13 >>> + a: 1; >> >> It's odd that this is indented when there's no groupings/selectors 🤔 > > It does indeed look odd in the test, but that's what we want to do to save formatted text — we need to send style declarations, which is everything inside of `selectior {...}`, but no selectors or groupings. To paraphrase, I need to add this newline at the start for the saved formatted text to make sense. For example, when I edit a CSS property in: #foo { font-size: 14px; } I don't want to save it as: #foo { font-size: 14px; }
Nikita Vasilyev
Comment 17 2021-07-28 14:56:59 PDT
Devin Rousso
Comment 18 2021-10-05 12:26:46 PDT
Comment on attachment 434469 [details] Patch View in context: https://bugs.webkit.org/attachment.cgi?id=434469&action=review r=me I still think it's a bit odd to have formatted text suddenly appear in the middle of a minified resource, but perhaps that could be a good thing as it would stand out more (and make subsequent edits easier). It's also fair to say that when viewing a minified resource Web Inspector should auto-format it anyways, so unless the developer manually changes back to the minified view or saves the file to disk they're unlikely to be bothered by this. Most developers spend their time in the Styles details sidebar panel in the Elements Tab anyways. > Source/WebInspectorUI/UserInterface/Models/CSSStyleDeclaration.js:499 > + if (options.includeGroupingsAndSelectors) { NIT: I'm just realizing now that this probably should be `includeSelectorsAndGroupings` since you can't have a grouping without selectors but you can have the opposite, but it's not a big deal :P
Razvan Caliman
Comment 19 2021-10-06 08:09:15 PDT
Created attachment 440369 [details] Patch Carry over R+; Address nit
Razvan Caliman
Comment 20 2021-10-07 09:43:56 PDT
Created attachment 440505 [details] Patch Carry over R+; reattach Nikita\'s original patch
EWS
Comment 21 2021-10-07 11:15:20 PDT
Committed r283723 (242647@main): <https://commits.webkit.org/242647@main> All reviewed patches have been landed. Closing bug and clearing flags on attachment 440505 [details].
Note You need to log in before you can comment on or make changes to this bug.