Merge pull request #132 from tophf/paste-mozilla
Editor: paste from Mozilla format
This commit is contained in:
commit
0c30be4544
|
@ -165,6 +165,10 @@
|
||||||
"message": "Enable",
|
"message": "Enable",
|
||||||
"description": "Label for the button to enable a style"
|
"description": "Label for the button to enable a style"
|
||||||
},
|
},
|
||||||
|
"exportLabel": {
|
||||||
|
"message": "Export",
|
||||||
|
"description": "Label for the button to export a style ('edit' page) or all styles ('manage' page)"
|
||||||
|
},
|
||||||
"findStylesForSite": {
|
"findStylesForSite": {
|
||||||
"message": "Find more styles for this site.",
|
"message": "Find more styles for this site.",
|
||||||
"description": "Text for a link that gets a list of styles for the current site"
|
"description": "Text for a link that gets a list of styles for the current site"
|
||||||
|
@ -181,6 +185,26 @@
|
||||||
"message": "Type a command name",
|
"message": "Type a command name",
|
||||||
"description": "Placeholder text of inputbox in keymap help popup on the edit style page. Must be very short"
|
"description": "Placeholder text of inputbox in keymap help popup on the edit style page. Must be very short"
|
||||||
},
|
},
|
||||||
|
"importLabel": {
|
||||||
|
"message": "Import",
|
||||||
|
"description": "Label for the button to import a style ('edit' page) or all styles ('manage' page)"
|
||||||
|
},
|
||||||
|
"importAppendLabel": {
|
||||||
|
"message": "Append to style",
|
||||||
|
"description": "Label for the button to import a style and append to the existing sections"
|
||||||
|
},
|
||||||
|
"importAppendTooltip": {
|
||||||
|
"message": "Append the imported style to current style",
|
||||||
|
"description": "Tooltip for the button to import a style and append to the existing sections"
|
||||||
|
},
|
||||||
|
"importReplaceLabel": {
|
||||||
|
"message": "Overwrite style",
|
||||||
|
"description": "Label for the button to import and overwrite current style"
|
||||||
|
},
|
||||||
|
"importReplaceTooltip": {
|
||||||
|
"message": "Discard contents of current style and overwrite it with the imported style",
|
||||||
|
"description": "Label for the button to import and overwrite current style"
|
||||||
|
},
|
||||||
"installUpdate": {
|
"installUpdate": {
|
||||||
"message": "Install update",
|
"message": "Install update",
|
||||||
"description": "Label for the button to install an update for a single style"
|
"description": "Label for the button to install an update for a single style"
|
||||||
|
@ -322,13 +346,21 @@
|
||||||
"message": "Sections",
|
"message": "Sections",
|
||||||
"description": "Title for the style sections section"
|
"description": "Title for the style sections section"
|
||||||
},
|
},
|
||||||
"styleToMozillaFormat": {
|
"styleMozillaFormatHeading": {
|
||||||
"message": "To Mozilla format",
|
"message": "Mozilla Format",
|
||||||
"description": "Label for the button that converts the code to Mozilla format"
|
"description": "Heading for the section with buttons to import/export Mozilla format of the style"
|
||||||
|
},
|
||||||
|
"styleFromMozillaFormatPrompt": {
|
||||||
|
"message": "Paste the Mozilla-format code",
|
||||||
|
"description": "Prompt in the dialog displayed after clicking 'Import from Mozilla format' button"
|
||||||
|
},
|
||||||
|
"styleToMozillaFormatTitle": {
|
||||||
|
"message": "Style in Mozilla format",
|
||||||
|
"description": "Title of the popup with the style code in Mozilla format, shown after pressing the Export button on Edit style page"
|
||||||
},
|
},
|
||||||
"styleToMozillaFormatHelp": {
|
"styleToMozillaFormatHelp": {
|
||||||
"message": "The Mozilla format of the code can be used with Stylish for Firefox and can be submitted to userstyles.org.",
|
"message": "The Mozilla format of the code can be used with Stylish for Firefox and can be submitted to userstyles.org.",
|
||||||
"description": "Help info for the button that converts the code to Mozilla format"
|
"description": "Help info for the Mozilla format header section that converts the code to/from Mozilla format"
|
||||||
},
|
},
|
||||||
"styleUpdate": {
|
"styleUpdate": {
|
||||||
"message": "Are you sure you want to update '$stylename$'?",
|
"message": "Are you sure you want to update '$stylename$'?",
|
||||||
|
|
|
@ -2061,21 +2061,24 @@ Parser.prototype = function(){
|
||||||
col: token.startCol
|
col: token.startCol
|
||||||
});
|
});
|
||||||
|
|
||||||
while(true) {
|
var ok = true;
|
||||||
if (tokenStream.peek() == Tokens.PAGE_SYM){
|
while(ok) {
|
||||||
this._page();
|
switch (tokenStream.peek()) {
|
||||||
} else if (tokenStream.peek() == Tokens.FONT_FACE_SYM){
|
case Tokens.PAGE_SYM: this._page(); break;
|
||||||
this._font_face();
|
case Tokens.FONT_FACE_SYM: this._font_face(); break;
|
||||||
} else if (tokenStream.peek() == Tokens.VIEWPORT_SYM){
|
case Tokens.VIEWPORT_SYM: this._viewport(); break;
|
||||||
this._viewport();
|
case Tokens.MEDIA_SYM: this._media(); break;
|
||||||
} else if (tokenStream.peek() == Tokens.MEDIA_SYM){
|
case Tokens.KEYFRAMES_SYM: this._keyframes(); break;
|
||||||
this._media();
|
case Tokens.DOCUMENT_SYM: this._document(); break;
|
||||||
} else if (!this._ruleset()){
|
default:
|
||||||
break;
|
if (!this._ruleset()) {
|
||||||
|
ok = false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
tokenStream.mustMatch(Tokens.RBRACE);
|
tokenStream.mustMatch(Tokens.RBRACE);
|
||||||
|
token = tokenStream.token();
|
||||||
this._readWhitespace();
|
this._readWhitespace();
|
||||||
|
|
||||||
this.fire({
|
this.fire({
|
||||||
|
@ -3259,6 +3262,7 @@ Parser.prototype = function(){
|
||||||
|
|
||||||
this._readWhitespace();
|
this._readWhitespace();
|
||||||
tokenStream.mustMatch(Tokens.RBRACE);
|
tokenStream.mustMatch(Tokens.RBRACE);
|
||||||
|
this._readWhitespace();
|
||||||
|
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|
28
edit.html
28
edit.html
|
@ -241,7 +241,7 @@
|
||||||
background-color: white;
|
background-color: white;
|
||||||
box-shadow: 3px 3px 30px rgba(0, 0, 0, 0.5);
|
box-shadow: 3px 3px 30px rgba(0, 0, 0, 0.5);
|
||||||
padding: 0.5rem;
|
padding: 0.5rem;
|
||||||
z-index: 9999;
|
z-index: 99;
|
||||||
}
|
}
|
||||||
#help-popup .title {
|
#help-popup .title {
|
||||||
font-weight: bold;
|
font-weight: bold;
|
||||||
|
@ -282,6 +282,19 @@
|
||||||
padding-right: 0.5rem;
|
padding-right: 0.5rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#help-popup button[name^="import"] {
|
||||||
|
line-height: 1.5rem;
|
||||||
|
padding: 0 0.5rem;
|
||||||
|
margin: 0.5rem 0 0 0.5rem;
|
||||||
|
pointer-events: none;
|
||||||
|
opacity: 0.5;
|
||||||
|
float: right;
|
||||||
|
}
|
||||||
|
#help-popup.ready button[name^="import"] {
|
||||||
|
pointer-events: all;
|
||||||
|
opacity: 1.0;
|
||||||
|
}
|
||||||
|
|
||||||
/************ lint ************/
|
/************ lint ************/
|
||||||
#lint {
|
#lint {
|
||||||
display: none;
|
display: none;
|
||||||
|
@ -528,9 +541,16 @@
|
||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
<section id="actions">
|
<section id="actions">
|
||||||
<div><button id="beautify" i18n-text="styleBeautify"></button> <button id="to-mozilla" i18n-text="styleToMozillaFormat"></button><img id="to-mozilla-help" src="help.png"></div>
|
<div>
|
||||||
<div><a href="manage.html"><button id="cancel-button" i18n-text="styleCancelEditLabel"></button></a></div>
|
<button id="save-button" title="Ctrl-S" i18n-text="styleSaveLabel"></button>
|
||||||
<div><button id="save-button" title="Ctrl-S" i18n-text="styleSaveLabel"></button></div>
|
<button id="beautify" i18n-text="styleBeautify"></button>
|
||||||
|
<a href="manage.html"><button id="cancel-button" i18n-text="styleCancelEditLabel"></button></a>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<h2 id="mozilla-format-heading" i18n-text="styleMozillaFormatHeading"><img id="to-mozilla-help" src="help.png"></h2>
|
||||||
|
<button id="from-mozilla" i18n-text="importLabel"></button>
|
||||||
|
<button id="to-mozilla" i18n-text="exportLabel"></button>
|
||||||
|
</div>
|
||||||
</section>
|
</section>
|
||||||
<section id="options">
|
<section id="options">
|
||||||
<h2 id="options-heading" i18n-text="optionsHeading"></h2>
|
<h2 id="options-heading" i18n-text="optionsHeading"></h2>
|
||||||
|
|
239
edit.js
239
edit.js
|
@ -18,12 +18,20 @@ var CssToProperty = {"url": "urls", "url-prefix": "urlPrefixes", "domain": "doma
|
||||||
// Chrome pre-34
|
// Chrome pre-34
|
||||||
Element.prototype.matches = Element.prototype.matches || Element.prototype.webkitMatchesSelector;
|
Element.prototype.matches = Element.prototype.matches || Element.prototype.webkitMatchesSelector;
|
||||||
|
|
||||||
|
// Chrome pre-41 polyfill
|
||||||
|
Element.prototype.closest = Element.prototype.closest || function(selector) {
|
||||||
|
for (var e = this; e && !e.matches(selector); e = e.parentElement) {}
|
||||||
|
return e;
|
||||||
|
};
|
||||||
|
|
||||||
Array.prototype.rotate = function(amount) { // negative amount == rotate left
|
Array.prototype.rotate = function(amount) { // negative amount == rotate left
|
||||||
var r = this.slice(-amount, this.length);
|
var r = this.slice(-amount, this.length);
|
||||||
Array.prototype.push.apply(r, this.slice(0, this.length - r.length));
|
Array.prototype.push.apply(r, this.slice(0, this.length - r.length));
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Object.defineProperty(Array.prototype, "last", {get: function() { return this[this.length - 1]; }});
|
||||||
|
|
||||||
// reroute handling to nearest editor when keypress resolves to one of these commands
|
// reroute handling to nearest editor when keypress resolves to one of these commands
|
||||||
var hotkeyRerouter = {
|
var hotkeyRerouter = {
|
||||||
commands: {
|
commands: {
|
||||||
|
@ -134,13 +142,8 @@ function initCodeMirror() {
|
||||||
"Alt-PageUp": "prevEditor"
|
"Alt-PageUp": "prevEditor"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
mergeOptions(stylishOptions, CM.defaults);
|
shallowMerge(stylishOptions, CM.defaults);
|
||||||
mergeOptions(userOptions, CM.defaults);
|
shallowMerge(userOptions, CM.defaults);
|
||||||
|
|
||||||
function mergeOptions(source, target) {
|
|
||||||
for (var key in source) target[key] = source[key];
|
|
||||||
return target;
|
|
||||||
}
|
|
||||||
|
|
||||||
// additional commands
|
// additional commands
|
||||||
CM.commands.jumpToLine = jumpToLine;
|
CM.commands.jumpToLine = jumpToLine;
|
||||||
|
@ -353,16 +356,21 @@ function indicateCodeChange(cm) {
|
||||||
}
|
}
|
||||||
|
|
||||||
function getSectionForCodeMirror(cm) {
|
function getSectionForCodeMirror(cm) {
|
||||||
return cm.getTextArea().parentNode;
|
return cm.display.wrapper.parentNode;
|
||||||
|
}
|
||||||
|
|
||||||
|
function getSectionForChild(e) {
|
||||||
|
return e.closest("#sections > div");
|
||||||
|
}
|
||||||
|
|
||||||
|
function getSections() {
|
||||||
|
return document.querySelectorAll("#sections > div");
|
||||||
}
|
}
|
||||||
|
|
||||||
function getCodeMirrorForSection(section) {
|
function getCodeMirrorForSection(section) {
|
||||||
// #header section has no codemirror
|
// #header section has no codemirror
|
||||||
var wrapper = section.querySelector(".CodeMirror");
|
var wrapper = section.querySelector(".CodeMirror");
|
||||||
if (wrapper) {
|
return wrapper && wrapper.CodeMirror;
|
||||||
return wrapper.CodeMirror;
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// remind Chrome to repaint a previously invisible editor box by toggling any element's transform
|
// remind Chrome to repaint a previously invisible editor box by toggling any element's transform
|
||||||
|
@ -490,7 +498,7 @@ function addSection(event, section) {
|
||||||
if (event) {
|
if (event) {
|
||||||
var clickedSection = event.target.parentNode;
|
var clickedSection = event.target.parentNode;
|
||||||
sections.insertBefore(div, clickedSection.nextElementSibling);
|
sections.insertBefore(div, clickedSection.nextElementSibling);
|
||||||
var newIndex = document.querySelectorAll("#sections > div").indexOf(clickedSection) + 1;
|
var newIndex = getSections().indexOf(clickedSection) + 1;
|
||||||
var cm = setupCodeMirror(codeElement, newIndex);
|
var cm = setupCodeMirror(codeElement, newIndex);
|
||||||
makeSectionVisible(cm);
|
makeSectionVisible(cm);
|
||||||
cm.focus()
|
cm.focus()
|
||||||
|
@ -515,7 +523,7 @@ function removeAppliesTo(event) {
|
||||||
|
|
||||||
function removeSection(event) {
|
function removeSection(event) {
|
||||||
var section = event.target.parentNode;
|
var section = event.target.parentNode;
|
||||||
var cm = section.querySelector(".CodeMirror").CodeMirror;
|
var cm = getCodeMirrorForSection(section);
|
||||||
removeAreaAndSetDirty(section);
|
removeAreaAndSetDirty(section);
|
||||||
editors.splice(editors.indexOf(cm), 1);
|
editors.splice(editors.indexOf(cm), 1);
|
||||||
renderLintReport();
|
renderLintReport();
|
||||||
|
@ -792,7 +800,7 @@ function getEditorInSight(nearbyElement) {
|
||||||
// priority: 1. associated CM for applies-to element 2. last active if visible 3. first visible
|
// priority: 1. associated CM for applies-to element 2. last active if visible 3. first visible
|
||||||
var cm;
|
var cm;
|
||||||
if (nearbyElement && nearbyElement.className.indexOf("applies-") >= 0) {
|
if (nearbyElement && nearbyElement.className.indexOf("applies-") >= 0) {
|
||||||
cm = getCodeMirrorForSection(querySelectorParent(nearbyElement, "#sections > div"));
|
cm = getCodeMirrorForSection(getSectionForChild(nearbyElement));
|
||||||
} else {
|
} else {
|
||||||
cm = editors.lastActive;
|
cm = editors.lastActive;
|
||||||
}
|
}
|
||||||
|
@ -933,11 +941,11 @@ function resizeLintReport(event, content) {
|
||||||
}
|
}
|
||||||
|
|
||||||
function gotoLintIssue(event) {
|
function gotoLintIssue(event) {
|
||||||
var issue = querySelectorParent(event.target, "tr");
|
var issue = event.target.closest("tr");
|
||||||
if (!issue) {
|
if (!issue) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
var block = querySelectorParent(issue, "table");
|
var block = issue.closest("table");
|
||||||
makeSectionVisible(block.cm);
|
makeSectionVisible(block.cm);
|
||||||
block.cm.focus();
|
block.cm.focus();
|
||||||
block.cm.setSelection({
|
block.cm.setSelection({
|
||||||
|
@ -960,7 +968,7 @@ function beautify(event) {
|
||||||
options.indent_size = tabs ? 1 : prefs.getPref("editor.tabSize");
|
options.indent_size = tabs ? 1 : prefs.getPref("editor.tabSize");
|
||||||
options.indent_char = tabs ? "\t" : " ";
|
options.indent_char = tabs ? "\t" : " ";
|
||||||
|
|
||||||
var section = querySelectorParent(event.target, "#sections > div");
|
var section = getSectionForChild(event.target);
|
||||||
var scope = section ? [getCodeMirrorForSection(section)] : editors;
|
var scope = section ? [getCodeMirrorForSection(section)] : editors;
|
||||||
|
|
||||||
showHelp(t("styleBeautify"), "<div class='beautify-options'>" +
|
showHelp(t("styleBeautify"), "<div class='beautify-options'>" +
|
||||||
|
@ -1063,9 +1071,7 @@ function initWithStyle(style) {
|
||||||
document.getElementById("enabled").checked = style.enabled == "true";
|
document.getElementById("enabled").checked = style.enabled == "true";
|
||||||
document.getElementById("url").href = style.url;
|
document.getElementById("url").href = style.url;
|
||||||
// if this was done in response to an update, we need to clear existing sections
|
// if this was done in response to an update, we need to clear existing sections
|
||||||
document.querySelectorAll("#sections > div").forEach(function(div) {
|
getSections().forEach(function(div) { div.remove(); });
|
||||||
div.parentNode.removeChild(div);
|
|
||||||
});
|
|
||||||
var queue = style.sections.length ? style.sections : [{code: ""}];
|
var queue = style.sections.length ? style.sections : [{code: ""}];
|
||||||
var queueStart = new Date().getTime();
|
var queueStart = new Date().getTime();
|
||||||
// after 100ms the sections will be added asynchronously
|
// after 100ms the sections will be added asynchronously
|
||||||
|
@ -1094,6 +1100,7 @@ function initHooks() {
|
||||||
});
|
});
|
||||||
document.getElementById("to-mozilla").addEventListener("click", showMozillaFormat, false);
|
document.getElementById("to-mozilla").addEventListener("click", showMozillaFormat, false);
|
||||||
document.getElementById("to-mozilla-help").addEventListener("click", showToMozillaHelp, false);
|
document.getElementById("to-mozilla-help").addEventListener("click", showToMozillaHelp, false);
|
||||||
|
document.getElementById("from-mozilla").addEventListener("click", fromMozillaFormat);
|
||||||
document.getElementById("beautify").addEventListener("click", beautify);
|
document.getElementById("beautify").addEventListener("click", beautify);
|
||||||
document.getElementById("save-button").addEventListener("click", save, false);
|
document.getElementById("save-button").addEventListener("click", save, false);
|
||||||
document.getElementById("sections-help").addEventListener("click", showSectionHelp, false);
|
document.getElementById("sections-help").addEventListener("click", showSectionHelp, false);
|
||||||
|
@ -1213,16 +1220,16 @@ function save() {
|
||||||
id: styleId,
|
id: styleId,
|
||||||
name: name,
|
name: name,
|
||||||
enabled: enabled,
|
enabled: enabled,
|
||||||
sections: getSections()
|
sections: getSectionsHashes()
|
||||||
};
|
};
|
||||||
chrome.extension.sendMessage(request, saveComplete);
|
chrome.extension.sendMessage(request, saveComplete);
|
||||||
}
|
}
|
||||||
|
|
||||||
function getSections() {
|
function getSectionsHashes() {
|
||||||
var sections = [];
|
var sections = [];
|
||||||
document.querySelectorAll("#sections > div").forEach(function(div) {
|
getSections().forEach(function(div) {
|
||||||
var meta = getMeta(div);
|
var meta = getMeta(div);
|
||||||
var code = div.querySelector(".CodeMirror").CodeMirror.getValue();
|
var code = getCodeMirrorForSection(div).getValue();
|
||||||
if (/^\s*$/.test(code) && Object.keys(meta).length == 0) {
|
if (/^\s*$/.test(code) && Object.keys(meta).length == 0) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -1261,11 +1268,13 @@ function saveComplete(style) {
|
||||||
}
|
}
|
||||||
|
|
||||||
function showMozillaFormat() {
|
function showMozillaFormat() {
|
||||||
window.open("data:text/plain;charset=UTF-8," + encodeURIComponent(toMozillaFormat()));
|
var popup = showCodeMirrorPopup(t("styleToMozillaFormatTitle"), "", {readOnly: true});
|
||||||
|
popup.codebox.setValue(toMozillaFormat());
|
||||||
|
popup.codebox.execCommand("selectAll");
|
||||||
}
|
}
|
||||||
|
|
||||||
function toMozillaFormat() {
|
function toMozillaFormat() {
|
||||||
return getSections().map(function(section) {
|
return getSectionsHashes().map(function(section) {
|
||||||
var cssMds = [];
|
var cssMds = [];
|
||||||
for (var i in propertyToCss) {
|
for (var i in propertyToCss) {
|
||||||
if (section[i]) {
|
if (section[i]) {
|
||||||
|
@ -1278,6 +1287,147 @@ function toMozillaFormat() {
|
||||||
}).join("\n\n");
|
}).join("\n\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function fromMozillaFormat() {
|
||||||
|
var popup = showCodeMirrorPopup(t("styleFromMozillaFormatPrompt"), tHTML("<div>\
|
||||||
|
<button name='import-append' i18n-text='importAppendLabel' i18n-title='importAppendTooltip'></button>\
|
||||||
|
<button name='import-replace' i18n-text='importReplaceLabel' i18n-title='importReplaceTooltip'></button>\
|
||||||
|
</div>").innerHTML);
|
||||||
|
|
||||||
|
var contents = popup.querySelector(".contents");
|
||||||
|
contents.insertBefore(popup.codebox.display.wrapper, contents.firstElementChild);
|
||||||
|
popup.codebox.focus();
|
||||||
|
|
||||||
|
popup.querySelector("[name='import-append']").addEventListener("click", doImport);
|
||||||
|
popup.querySelector("[name='import-replace']").addEventListener("click", doImport);
|
||||||
|
|
||||||
|
popup.codebox.on("change", function() {
|
||||||
|
clearTimeout(popup.mozillaTimeout);
|
||||||
|
popup.mozillaTimeout = setTimeout(function() {
|
||||||
|
popup.classList.toggle("ready", trimNewLines(popup.codebox.getValue()));
|
||||||
|
}, 100);
|
||||||
|
});
|
||||||
|
|
||||||
|
function doImport() {
|
||||||
|
var replaceOldStyle = this.name == "import-replace";
|
||||||
|
popup.querySelector(".close-icon").click();
|
||||||
|
var mozStyle = trimNewLines(popup.codebox.getValue());
|
||||||
|
var parser = new exports.css.Parser(), lines = mozStyle.split("\n");
|
||||||
|
var sectionStack = [{code: "", cursor: {line: 1, col: 1}}];
|
||||||
|
var errors = "", oldSectionCount = editors.length;
|
||||||
|
|
||||||
|
parser.addListener("startdocument", function(e) {
|
||||||
|
var outerText = getRange(sectionStack.last.cursor, (--e.col, e));
|
||||||
|
var gapComment = outerText.match(/(\/\*[\s\S]*?\*\/)[\s\n]*$/);
|
||||||
|
var section = {code: "", cursor: backtrackTo(this, exports.css.Tokens.LBRACE, "end")};
|
||||||
|
// move last comment before @-moz-document inside the section
|
||||||
|
if (gapComment && !gapComment[1].match(/\/\*\s*AGENT_SHEET\s*\*\//)) {
|
||||||
|
section.code = gapComment[1] + "\n";
|
||||||
|
outerText = trimNewLines(outerText.substring(0, gapComment.index));
|
||||||
|
}
|
||||||
|
addContinuation(sectionStack.last, outerText);
|
||||||
|
e.functions.forEach(function(f) {
|
||||||
|
var m = f.match(/^(url|url-prefix|domain|regexp)\((['"]?)(.+?)\2?\)$/);
|
||||||
|
var aType = CssToProperty[m[1]];
|
||||||
|
var aValue = aType != "regexps" ? m[3] : m[3].replace(/\\\\/g, "\\");
|
||||||
|
(section[aType] = section[aType] || []).push(aValue);
|
||||||
|
});
|
||||||
|
sectionStack.push(section);
|
||||||
|
});
|
||||||
|
|
||||||
|
parser.addListener("enddocument", function(e) {
|
||||||
|
var cursor = backtrackTo(this, exports.css.Tokens.RBRACE, "start");
|
||||||
|
var section = sectionStack.pop();
|
||||||
|
addContinuation(section, getRange(section.cursor, cursor));
|
||||||
|
sectionStack.last.cursor = (++cursor.col, cursor);
|
||||||
|
doAddSection(section);
|
||||||
|
});
|
||||||
|
|
||||||
|
parser.addListener("endstylesheet", function() {
|
||||||
|
// add nonclosed (broken) outer sections except for the global one
|
||||||
|
sectionStack.slice(1).forEach(doAddSection);
|
||||||
|
|
||||||
|
if (!replaceOldStyle) {
|
||||||
|
var lastOldCM = editors[oldSectionCount - 1];
|
||||||
|
var lastOldSection = getSectionForCodeMirror(lastOldCM);
|
||||||
|
var addAfter = {target: lastOldSection.querySelector(".add-section")};
|
||||||
|
|
||||||
|
if (oldSectionCount < editors.length
|
||||||
|
&& lastOldCM.getValue() == ""
|
||||||
|
&& lastOldSection.querySelector(".applies-to-everything")) {
|
||||||
|
removeSection(addAfter);
|
||||||
|
oldSectionCount--;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
var addAfter = {target: getSectionForCodeMirror(editors[0]).previousElementSibling.firstElementChild};
|
||||||
|
}
|
||||||
|
|
||||||
|
var globalSection = sectionStack[0];
|
||||||
|
addContinuation(globalSection,
|
||||||
|
getRange(sectionStack.last.cursor, {line: lines.length, col: lines.last.length + 1}));
|
||||||
|
// only add global section if it contains actual code
|
||||||
|
if (globalSection.code
|
||||||
|
.replace("@namespace url(http://www.w3.org/1999/xhtml);", "") /* strip boilerplate NS */
|
||||||
|
.replace(/\/\*[\s\S]*?\*\//g, "") /* strip comments */
|
||||||
|
.replace(/[\s\n]/g, "")) { /* strip all whitespace including new lines */
|
||||||
|
setCleanItem(addSection(addAfter, {code: globalSection.code}), false);
|
||||||
|
}
|
||||||
|
|
||||||
|
delete maximizeCodeHeight.stats;
|
||||||
|
editors.forEach(function(cm, i) {
|
||||||
|
maximizeCodeHeight(getSectionForCodeMirror(cm), i == editors.length - 1);
|
||||||
|
});
|
||||||
|
|
||||||
|
makeSectionVisible(editors[oldSectionCount]);
|
||||||
|
editors[oldSectionCount].focus();
|
||||||
|
if (errors) {
|
||||||
|
showHelp(t("issues"), errors);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
parser.addListener("error", function(e) {
|
||||||
|
errors += e.line + ":" + e.col + " " + e.message.replace(/ at line \d.+$/, "") + "<br>";
|
||||||
|
});
|
||||||
|
|
||||||
|
parser.parse(mozStyle);
|
||||||
|
|
||||||
|
function getRange(start, end) {
|
||||||
|
if (start.line == end.line) {
|
||||||
|
return lines[start.line - 1].substring(start.col - 1, end.col - 1).trim();
|
||||||
|
} else {
|
||||||
|
return trimNewLines(lines[start.line - 1].substr(start.col - 1) + "\n" +
|
||||||
|
lines.slice(start.line, end.line - 1).join("\n") +
|
||||||
|
"\n" + lines[end.line - 1].substring(0, end.col - 1));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
function doAddSection(section) {
|
||||||
|
if (replaceOldStyle && oldSectionCount > 0) {
|
||||||
|
oldSectionCount = 0;
|
||||||
|
editors.slice(0).reverse().forEach(function(cm) {
|
||||||
|
removeSection({target: getSectionForCodeMirror(cm).firstElementChild});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
setCleanItem(addSection(null, section), false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
function backtrackTo(parser, tokenType, startEnd) {
|
||||||
|
var tokens = parser._tokenStream._lt;
|
||||||
|
for (var i = tokens.length - 2; i >= 0; --i) {
|
||||||
|
if (tokens[i].type == tokenType) {
|
||||||
|
return {line: tokens[i][startEnd+"Line"], col: tokens[i][startEnd+"Col"]};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
function trimNewLines(s) {
|
||||||
|
return s.replace(/^[\s\n]+/, "").replace(/[\s\n]+$/, "");
|
||||||
|
}
|
||||||
|
function addContinuation(section, addendum) {
|
||||||
|
section.code = section.code && addendum
|
||||||
|
? section.code + "\n/**************************/\n" + addendum
|
||||||
|
: section.code || addendum;
|
||||||
|
return section.code;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
function showSectionHelp() {
|
function showSectionHelp() {
|
||||||
showHelp(t("styleSectionsTitle"), t("sectionHelp"));
|
showHelp(t("styleSectionsTitle"), t("sectionHelp"));
|
||||||
}
|
}
|
||||||
|
@ -1287,7 +1437,7 @@ function showAppliesToHelp() {
|
||||||
}
|
}
|
||||||
|
|
||||||
function showToMozillaHelp() {
|
function showToMozillaHelp() {
|
||||||
showHelp(t("styleToMozillaFormat"), t("styleToMozillaFormatHelp"));
|
showHelp(t("styleMozillaFormatHeading"), t("styleToMozillaFormatHelp"));
|
||||||
}
|
}
|
||||||
|
|
||||||
function showKeyMapHelp() {
|
function showKeyMapHelp() {
|
||||||
|
@ -1379,6 +1529,7 @@ function showLintHelp() {
|
||||||
|
|
||||||
function showHelp(title, text) {
|
function showHelp(title, text) {
|
||||||
var div = document.getElementById("help-popup");
|
var div = document.getElementById("help-popup");
|
||||||
|
div.style.cssText = "";
|
||||||
div.querySelector(".contents").innerHTML = text;
|
div.querySelector(".contents").innerHTML = text;
|
||||||
div.querySelector(".title").innerHTML = title;
|
div.querySelector(".title").innerHTML = title;
|
||||||
|
|
||||||
|
@ -1388,15 +1539,40 @@ function showHelp(title, text) {
|
||||||
}
|
}
|
||||||
|
|
||||||
div.style.display = "block";
|
div.style.display = "block";
|
||||||
|
return div;
|
||||||
|
|
||||||
function closeHelp(e) {
|
function closeHelp(e) {
|
||||||
if (e.type == "click" || (e.keyCode == 27 && !e.altKey && !e.ctrlKey && !e.shiftKey && !e.metaKey)) {
|
if (e.type == "click" || (e.keyCode == 27 && !e.altKey && !e.ctrlKey && !e.shiftKey && !e.metaKey)) {
|
||||||
div.style.display = "";
|
div.style.display = "";
|
||||||
|
document.querySelector(".contents").innerHTML = "";
|
||||||
document.removeEventListener("keydown", closeHelp);
|
document.removeEventListener("keydown", closeHelp);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function showCodeMirrorPopup(title, html, options) {
|
||||||
|
var popup = showHelp(title, html);
|
||||||
|
popup.style.width = popup.style.maxWidth = "calc(100vw - 7rem)";
|
||||||
|
|
||||||
|
popup.codebox = CodeMirror(popup.querySelector(".contents"), shallowMerge(options, {
|
||||||
|
mode: "css",
|
||||||
|
lineNumbers: true,
|
||||||
|
lineWrapping: true,
|
||||||
|
foldGutter: true,
|
||||||
|
gutters: ["CodeMirror-linenumbers", "CodeMirror-foldgutter", "CodeMirror-lint-markers"],
|
||||||
|
matchBrackets: true,
|
||||||
|
lint: {getAnnotations: CodeMirror.lint.css, delay: 0},
|
||||||
|
styleActiveLine: true,
|
||||||
|
theme: prefs.getPref("editor.theme"),
|
||||||
|
keyMap: prefs.getPref("editor.keyMap")
|
||||||
|
}));
|
||||||
|
popup.codebox.focus();
|
||||||
|
popup.codebox.setSize(null, "70vh");
|
||||||
|
popup.codebox.on("focus", function() { hotkeyRerouter.setState(false) });
|
||||||
|
popup.codebox.on("blur", function() { hotkeyRerouter.setState(true) });
|
||||||
|
return popup;
|
||||||
|
}
|
||||||
|
|
||||||
function getParams() {
|
function getParams() {
|
||||||
var params = {};
|
var params = {};
|
||||||
var urlParts = location.href.split("?", 2);
|
var urlParts = location.href.split("?", 2);
|
||||||
|
@ -1430,13 +1606,6 @@ chrome.extension.onMessage.addListener(function(request, sender, sendResponse) {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
function querySelectorParent(node, selector) {
|
|
||||||
var parent = node.parentNode;
|
|
||||||
while (parent && parent.matches && !parent.matches(selector))
|
|
||||||
parent = parent.parentNode;
|
|
||||||
return parent.matches ? parent : null; // null for the root document.DOCUMENT_NODE
|
|
||||||
}
|
|
||||||
|
|
||||||
function stringAsRegExp(s, flags) {
|
function stringAsRegExp(s, flags) {
|
||||||
return new RegExp(s.replace(/[{}()\[\]\/\\.+?^$:=*!|]/g, "\\$&"), flags);
|
return new RegExp(s.replace(/[{}()\[\]\/\\.+?^$:=*!|]/g, "\\$&"), flags);
|
||||||
}
|
}
|
||||||
|
|
14
storage.js
14
storage.js
|
@ -262,14 +262,16 @@ function sessionStorageHash(name) {
|
||||||
}
|
}
|
||||||
|
|
||||||
function shallowCopy(obj) {
|
function shallowCopy(obj) {
|
||||||
if (typeof obj != "object") {
|
return typeof obj == "object" ? shallowMerge(obj, {}) : obj;
|
||||||
return obj;
|
}
|
||||||
|
|
||||||
|
function shallowMerge(from, to) {
|
||||||
|
if (typeof from == "object" && typeof to == "object") {
|
||||||
|
for (var k in from) {
|
||||||
|
to[k] = from[k];
|
||||||
}
|
}
|
||||||
var copy = {};
|
|
||||||
for (var k in obj) {
|
|
||||||
copy[k] = obj[k];
|
|
||||||
}
|
}
|
||||||
return copy;
|
return to;
|
||||||
}
|
}
|
||||||
|
|
||||||
function equal(a, b) {
|
function equal(a, b) {
|
||||||
|
|
Loading…
Reference in New Issue
Block a user