From b5df8802a0f789c026f378a8cd9b20d15595b063 Mon Sep 17 00:00:00 2001 From: tophf Date: Tue, 23 Jun 2015 19:24:53 +0300 Subject: [PATCH] Editor: CSS-beautifier --- _locales/en/messages.json | 4 +++ edit.html | 26 ++++++++++++++++-- edit.js | 58 +++++++++++++++++++++++++++++++++++++++ storage.js | 9 ++++++ 4 files changed, 95 insertions(+), 2 deletions(-) diff --git a/_locales/en/messages.json b/_locales/en/messages.json index 3c601a09..4b1ee918 100644 --- a/_locales/en/messages.json +++ b/_locales/en/messages.json @@ -261,6 +261,10 @@ "message": "Regexp is invalid.", "description": "Validation message for a bad regexp in a style" }, + "styleBeautify": { + "message": "Beautify", + "description": "Label for the CSS-beautifier button on the edit style page" + }, "styleCancelEditLabel": { "message": "Back to manage", "description": "Label for cancel button for style editing" diff --git a/edit.html b/edit.html index 1cc4fe9c..d7ae3780 100644 --- a/edit.html +++ b/edit.html @@ -124,7 +124,7 @@ #sections > div:only-of-type .remove-section { display: none; } - #sections > div .add-section { + #sections > div > button:not(:first-of-type) { margin-left: 0.4rem; } .dirty > label::before { @@ -316,6 +316,28 @@ text-align: left; } + /************ CSS beautifier ************/ + .beautify-options { + white-space: nowrap; + font-family: monospace; + } + .beautify-options div { + float: left; + } + .beautify-options div[newline="true"] + div { + clear: left; + } + .beautify-options div[newline="true"] + div span[indent] { + padding-left: 2rem; + } + .beautify-options span { + font-weight: bold; + } + .beautify-options select { + border: none; + background-color: rgba(0, 0, 0, 0.05); + } + /************ reponsive layouts ************/ @media(max-width:737px) { #header { @@ -425,7 +447,7 @@
-
+
diff --git a/edit.js b/edit.js index 21be4680..492c4e1b 100644 --- a/edit.js +++ b/edit.js @@ -44,6 +44,7 @@ var sectionTemplate = tHTML('\ \ \ \ + \ \ '); @@ -483,6 +484,7 @@ function addSection(event, section) { div.querySelector(".applies-to-help").addEventListener("click", showAppliesToHelp, false); div.querySelector(".remove-section").addEventListener("click", removeSection, false); div.querySelector(".add-section").addEventListener("click", addSection, false); + div.querySelector(".beautify-section").addEventListener("click", beautify); var codeElement = div.querySelector(".code"); var appliesTo = div.querySelector(".applies-to-list"); @@ -825,6 +827,61 @@ function gotoLintIssue(event) { }); } +function beautify(event) { + if (exports.css_beautify) { // thanks to csslint's definition of 'exports' + doBeautify(); + } else { + var script = document.head.appendChild(document.createElement("script")); + script.src = "beautify/beautify-css.js"; + script.onload = doBeautify; + } + function doBeautify() { + var tabs = prefs.getPref("editor.indentWithTabs"); + var options = prefs.getPref("editor.beautify"); + options.indent_size = tabs ? 1 : prefs.getPref("editor.tabSize"); + options.indent_char = tabs ? "\t" : " "; + + var section = querySelectorParent(event.target, "#sections > div"); + var scope = section ? [getCodeMirrorForSection(section)] : editors; + scope.forEach(function(cm) { + setTimeout(function() { + var text = cm.getValue(); + var newText = exports.css_beautify(text, options); + if (newText != text) { + cm.setValue(newText); + } + }, 0); + }); + + showHelp(t("styleBeautify"), "
" + + optionHtml(".selector1,", "selector_separator_newline") + + optionHtml(".selector2,", "newline_before_open_brace") + + optionHtml("{", "newline_after_open_brace") + + optionHtml("border: none;", "newline_between_properties", true) + + optionHtml("display: block;", "newline_before_close_brace", true) + + optionHtml("}", "newline_between_rules") + + "
"); + + document.querySelector(".beautify-options").addEventListener("change", function(event) { + var value = event.target.selectedIndex > 0; + options[event.target.dataset.option] = value; + prefs.setPref("editor.beautify", options); + event.target.parentNode.setAttribute("newline", value.toString()); + doBeautify(); + }); + + function optionHtml(label, optionName, indent) { + var value = options[optionName]; + return "
" + + "" + label + "" + + "
"; + } + } +} + window.addEventListener("load", init, false); function init() { @@ -883,6 +940,7 @@ function initHooks() { }); document.getElementById("to-mozilla").addEventListener("click", showMozillaFormat, false); document.getElementById("to-mozilla-help").addEventListener("click", showToMozillaHelp, false); + document.getElementById("beautify").addEventListener("click", beautify); document.getElementById("save-button").addEventListener("click", save, false); document.getElementById("sections-help").addEventListener("click", showSectionHelp, false); document.getElementById("keyMap-help").addEventListener("click", showKeyMapHelp, false); diff --git a/storage.js b/storage.js index f7f03cdc..6cddff58 100644 --- a/storage.js +++ b/storage.js @@ -180,6 +180,15 @@ var prefs = { "editor.tabSize": 4, // tab width, in spaces "editor.keyMap": navigator.appVersion.indexOf("Windows") > 0 ? "sublime" : "default", "editor.theme": "default", // CSS theme + "editor.beautify": { // CSS beautifier + selector_separator_newline: true, + newline_before_open_brace: false, + newline_after_open_brace: true, + newline_between_properties: true, + newline_before_close_brace: true, + newline_between_rules: false, + end_with_newline: false + }, NO_DEFAULT_PREFERENCE: "No default preference for '%s'", UNHANDLED_DATA_TYPE: "Default '%s' is of type '%s' - what should be done with it?",