From ad8706e107055994dec9b94f7cdf4df73a1a3dc8 Mon Sep 17 00:00:00 2001 From: tophf Date: Tue, 2 Feb 2016 08:30:08 +0200 Subject: [PATCH] Editor: preserve intermediary global sections on import Because the order of sections influences which rules will apply when several matching rules are present both in a global section and previously declared scoped one. --- edit.js | 97 ++++++++++++++++++++++++++++----------------------------- 1 file changed, 48 insertions(+), 49 deletions(-) diff --git a/edit.js b/edit.js index 137e2ca7..eca104e4 100644 --- a/edit.js +++ b/edit.js @@ -1332,19 +1332,24 @@ function fromMozillaFormat() { 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 sectionStack = [{code: "", start: {line: 1, col: 1}}]; var errors = "", oldSectionCount = editors.length; + var firstAddedCM; parser.addListener("startdocument", function(e) { - var outerText = getRange(sectionStack.last.cursor, (--e.col, e)); + var outerText = getRange(sectionStack.last.start, (--e.col, e)); var gapComment = outerText.match(/(\/\*[\s\S]*?\*\/)[\s\n]*$/); - var section = {code: "", cursor: backtrackTo(this, exports.css.Tokens.LBRACE, "end")}; + var section = {code: "", start: 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); + if (outerText) { + sectionStack.last.code = outerText; + doAddSection(sectionStack.last); + sectionStack.last.code = ""; + } e.functions.forEach(function(f) { var m = f.match(/^(url|url-prefix|domain|regexp)\((['"]?)(.+?)\2?\)$/); var aType = CssToProperty[m[1]]; @@ -1355,50 +1360,27 @@ function fromMozillaFormat() { }); parser.addListener("enddocument", function(e) { - var cursor = backtrackTo(this, exports.css.Tokens.RBRACE, "start"); + var end = backtrackTo(this, exports.css.Tokens.RBRACE, "start"); var section = sectionStack.pop(); - addContinuation(section, getRange(section.cursor, cursor)); - sectionStack.last.cursor = (++cursor.col, cursor); + section.code += getRange(section.start, end); + sectionStack.last.start = (++end.col, end); 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 = lastOldCM.getSection(); - 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: editors[0].getSection().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); - } + // add nonclosed outer sections (either broken or the last global one) + var endOfText = {line: lines.length, col: lines.last.length + 1}; + sectionStack.last.code += getRange(sectionStack.last.start, endOfText); + sectionStack.forEach(doAddSection); delete maximizeCodeHeight.stats; - editors.forEach(function(cm, i) { - maximizeCodeHeight(cm.getSection(), i == editors.length - 1); + editors.forEach(function(cm) { + maximizeCodeHeight(cm.getSection(), cm == editors.last); }); - makeSectionVisible(editors[oldSectionCount]); - editors[oldSectionCount].focus(); + makeSectionVisible(firstAddedCM); + firstAddedCM.focus(); + if (errors) { showHelp(t("issues"), errors); } @@ -1412,7 +1394,7 @@ function fromMozillaFormat() { function getRange(start, end) { if (start.line == end.line) { - return lines[start.line - 1].substring(start.col - 1, end.col - 1).trim(); + return lines[start.line - 1].substr(start.col - 1, end.col - start.col + 1).trim(); } else { return trimNewLines(lines[start.line - 1].substr(start.col - 1) + "\n" + lines.slice(start.line, end.line - 1).join("\n") + @@ -1420,13 +1402,36 @@ function fromMozillaFormat() { } } function doAddSection(section) { - if (replaceOldStyle && oldSectionCount > 0) { - oldSectionCount = 0; + if (!firstAddedCM) { + if (!initFirstSection(section)) { + return; + } + } + // don't add empty sections + if (!(section.code || section.urls || section.urlPrefixes || section.domains || section.regexps)) { + return; + } + setCleanItem(addSection(null, section), false); + firstAddedCM = firstAddedCM || editors.last; + } + // do onetime housekeeping as the imported text is confirmed to be a valid style + function initFirstSection(section) { + // skip adding the first global section when there's no code/comments + if (!section.code.replace("@namespace url(http://www.w3.org/1999/xhtml);", "") /* ignore boilerplate NS */ + .replace(/[\s\n]/g, "")) { /* ignore all whitespace including new lines */ + return false; + } + if (replaceOldStyle) { editors.slice(0).reverse().forEach(function(cm) { removeSection({target: cm.getSection().firstElementChild}); }); + } else if (!editors.last.getValue()) { + // nuke the last blank section + if (editors.last.getSection().querySelector(".applies-to-everything")) { + removeSection({target: editors.last.getSection()}); + } } - setCleanItem(addSection(null, section), false); + return true; } } function backtrackTo(parser, tokenType, startEnd) { @@ -1440,12 +1445,6 @@ function fromMozillaFormat() { 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() {