diff --git a/dist/csslint-node.js b/dist/csslint-node.js index e4df27fd..e4a627f5 100644 --- a/dist/csslint-node.js +++ b/dist/csslint-node.js @@ -1820,7 +1820,7 @@ CSSLint.addRule({ // rule information id: "outline-none", name: "Disallow outline: none", - desc: "Use of outline: none or outline: 0 should be limited to :focus rules.", + desc: "Use of outline: none | 0 | transparent should be limited to :focus rules and resulting elements should be visible.", url: "https://github.com/CSSLint/csslint/wiki/Disallow-outline%3Anone", browsers: "All", tags: ["Accessibility"], @@ -1838,7 +1838,8 @@ CSSLint.addRule({ col: event.col, selectors: event.selectors, propCount: 0, - outline: false + outline: false, + potentiallyInvisibleElement: false }; } else { lastRule = null; @@ -1850,7 +1851,7 @@ CSSLint.addRule({ if (lastRule.outline) { if (lastRule.selectors.toString().toLowerCase().indexOf(":focus") === -1) { reporter.report("Outlines should only be modified using :focus.", lastRule.line, lastRule.col, rule); - } else if (lastRule.propCount === 1) { + } else if (lastRule.propCount === 1 || lastRule.potentiallyInvisibleElement === true) { reporter.report("Outlines shouldn't be hidden unless other visual changes are made.", lastRule.line, lastRule.col, rule); } } @@ -1865,13 +1866,23 @@ CSSLint.addRule({ parser.addListener("startviewport", startRule); parser.addListener("property", function(event) { + var name = event.property.text.toLowerCase(), - value = event.value; + valueString = event.value.toString().toLowerCase(); if (lastRule) { lastRule.propCount++; - if (name === "outline" && (value.toString() === "none" || value.toString() === "0")) { - lastRule.outline = true; + + if (valueString.indexOf("none") !== -1 || valueString.indexOf("0") !== -1 || valueString.indexOf("transparent") !== -1) { + if (name === "outline") { + lastRule.outline = true; + } + else { + // these properties must not be 0, none, or transparent when outline is already one of those values + if (name.indexOf("border") >= 0) { + lastRule.potentiallyInvisibleElement = true; + } + } } } diff --git a/dist/csslint-rhino.js b/dist/csslint-rhino.js index 09be3ee8..c94f7abc 100644 --- a/dist/csslint-rhino.js +++ b/dist/csslint-rhino.js @@ -9378,7 +9378,7 @@ CSSLint.addRule({ // rule information id: "outline-none", name: "Disallow outline: none", - desc: "Use of outline: none or outline: 0 should be limited to :focus rules.", + desc: "Use of outline: none | 0 | transparent should be limited to :focus rules and resulting elements should be visible.", url: "https://github.com/CSSLint/csslint/wiki/Disallow-outline%3Anone", browsers: "All", tags: ["Accessibility"], @@ -9396,7 +9396,8 @@ CSSLint.addRule({ col: event.col, selectors: event.selectors, propCount: 0, - outline: false + outline: false, + potentiallyInvisibleElement: false }; } else { lastRule = null; @@ -9408,7 +9409,7 @@ CSSLint.addRule({ if (lastRule.outline) { if (lastRule.selectors.toString().toLowerCase().indexOf(":focus") === -1) { reporter.report("Outlines should only be modified using :focus.", lastRule.line, lastRule.col, rule); - } else if (lastRule.propCount === 1) { + } else if (lastRule.propCount === 1 || lastRule.potentiallyInvisibleElement === true) { reporter.report("Outlines shouldn't be hidden unless other visual changes are made.", lastRule.line, lastRule.col, rule); } } @@ -9423,13 +9424,23 @@ CSSLint.addRule({ parser.addListener("startviewport", startRule); parser.addListener("property", function(event) { + var name = event.property.text.toLowerCase(), - value = event.value; + valueString = event.value.toString().toLowerCase(); if (lastRule) { lastRule.propCount++; - if (name === "outline" && (value.toString() === "none" || value.toString() === "0")) { - lastRule.outline = true; + + if (valueString.indexOf("none") !== -1 || valueString.indexOf("0") !== -1 || valueString.indexOf("transparent") !== -1) { + if (name === "outline") { + lastRule.outline = true; + } + else { + // these properties must not be 0, none, or transparent when outline is already one of those values + if (name.indexOf("border") >= 0) { + lastRule.potentiallyInvisibleElement = true; + } + } } } diff --git a/dist/csslint-tests.js b/dist/csslint-tests.js index 85f03eba..4a8d9036 100644 --- a/dist/csslint-tests.js +++ b/dist/csslint-tests.js @@ -3096,6 +3096,13 @@ background: -o-linear-gradient(top, #1e5799 ,#2989d8 ,#207cca ,#7db9e8 ); Assert.areEqual("Outlines should only be modified using :focus.", result.messages[0].message); }, + "Using outline: transparent should result in a warning": function() { + var result = CSSLint.verify(".foo { outline: transparent}", { "outline-none": 1 }); + Assert.areEqual(1, result.messages.length); + Assert.areEqual("warning", result.messages[0].type); + Assert.areEqual("Outlines should only be modified using :focus.", result.messages[0].message); + }, + "Using outline: 0 should result in a warning": function() { var result = CSSLint.verify(".foo { outline: 0; }", { "outline-none": 1 }); Assert.areEqual(1, result.messages.length); @@ -3117,16 +3124,55 @@ background: -o-linear-gradient(top, #1e5799 ,#2989d8 ,#207cca ,#7db9e8 ); Assert.areEqual("Outlines shouldn't be hidden unless other visual changes are made.", result.messages[0].message); }, - "Using outline: none with :focus and another property should not result in a warning": function() { + "Using outline: transparent alone with :focus should result in a warning": function() { + var result = CSSLint.verify(".foo:focus { outline: transparent; }", { "outline-none": 1 }); + Assert.areEqual(1, result.messages.length); + Assert.areEqual("warning", result.messages[0].type); + Assert.areEqual("Outlines shouldn't be hidden unless other visual changes are made.", result.messages[0].message); + }, + + "Using outline: none with :focus and another visible property should not result in a warning": function() { var result = CSSLint.verify(".foo:focus { outline: none; border: 1px solid black; }", { "outline-none": 1 }); Assert.areEqual(0, result.messages.length); }, - "Using outline: 0 with :focus and another property should not result in a warning": function() { + "Using outline: 0 with :focus and another visible property should not result in a warning": function() { var result = CSSLint.verify(".foo:focus { outline: 0; border: 1px solid black;}", { "outline-none": 1 }); Assert.areEqual(0, result.messages.length); - } + }, + + "Using outline: 1px solid transparent; with :focus should result in a warning": function() { + var result = CSSLint.verify(".foo:focus { outline: 1px solid transparent;}", { "outline-none": 1 }); + Assert.areEqual(1, result.messages.length); + Assert.areEqual("warning", result.messages[0].type); + Assert.areEqual("Outlines shouldn't be hidden unless other visual changes are made.", result.messages[0].message); + }, + "Using outline: 0 with :focus and another transparent property should result in a warning": function() { + var result = CSSLint.verify(".foo:focus { outline: 0; border: 1px solid transparent;}", { "outline-none": 1 }); + Assert.areEqual(1, result.messages.length); + Assert.areEqual("warning", result.messages[0].type); + Assert.areEqual("Outlines shouldn't be hidden unless other visual changes are made.", result.messages[0].message); + }, + + "Using outline: 0 with :focus and another zeroed property should result in a warning": function() { + var result = CSSLint.verify(".foo:focus { outline: 0; border: 0 solid black;}", { "outline-none": 1 }); + Assert.areEqual(1, result.messages.length); + Assert.areEqual("warning", result.messages[0].type); + Assert.areEqual("Outlines shouldn't be hidden unless other visual changes are made.", result.messages[0].message); + }, + + "Using outline: 0 red; with :focus should result in a warning": function() { + var result = CSSLint.verify(".foo:focus { outline: 0 red;}", { "outline-none": 1 }); + Assert.areEqual(1, result.messages.length); + Assert.areEqual("warning", result.messages[0].type); + Assert.areEqual("Outlines shouldn't be hidden unless other visual changes are made.", result.messages[0].message); + }, + + "Using outline: 0 with :focus and another zeroed property that does not affect rendering should not result in a warning": function() { + var result = CSSLint.verify(".foo:focus { outline: 0; margin: 0;}", { "outline-none": 1 }); + Assert.areEqual(0, result.messages.length); + } })); })(); diff --git a/dist/csslint-worker.js b/dist/csslint-worker.js index c9781509..681f6c8b 100644 --- a/dist/csslint-worker.js +++ b/dist/csslint-worker.js @@ -9374,7 +9374,7 @@ CSSLint.addRule({ // rule information id: "outline-none", name: "Disallow outline: none", - desc: "Use of outline: none or outline: 0 should be limited to :focus rules.", + desc: "Use of outline: none | 0 | transparent should be limited to :focus rules and resulting elements should be visible.", url: "https://github.com/CSSLint/csslint/wiki/Disallow-outline%3Anone", browsers: "All", tags: ["Accessibility"], @@ -9392,7 +9392,8 @@ CSSLint.addRule({ col: event.col, selectors: event.selectors, propCount: 0, - outline: false + outline: false, + potentiallyInvisibleElement: false }; } else { lastRule = null; @@ -9404,7 +9405,7 @@ CSSLint.addRule({ if (lastRule.outline) { if (lastRule.selectors.toString().toLowerCase().indexOf(":focus") === -1) { reporter.report("Outlines should only be modified using :focus.", lastRule.line, lastRule.col, rule); - } else if (lastRule.propCount === 1) { + } else if (lastRule.propCount === 1 || lastRule.potentiallyInvisibleElement === true) { reporter.report("Outlines shouldn't be hidden unless other visual changes are made.", lastRule.line, lastRule.col, rule); } } @@ -9419,13 +9420,23 @@ CSSLint.addRule({ parser.addListener("startviewport", startRule); parser.addListener("property", function(event) { + var name = event.property.text.toLowerCase(), - value = event.value; + valueString = event.value.toString().toLowerCase(); if (lastRule) { lastRule.propCount++; - if (name === "outline" && (value.toString() === "none" || value.toString() === "0")) { - lastRule.outline = true; + + if (valueString.indexOf("none") !== -1 || valueString.indexOf("0") !== -1 || valueString.indexOf("transparent") !== -1) { + if (name === "outline") { + lastRule.outline = true; + } + else { + // these properties must not be 0, none, or transparent when outline is already one of those values + if (name.indexOf("border") >= 0) { + lastRule.potentiallyInvisibleElement = true; + } + } } } diff --git a/dist/csslint-wsh.js b/dist/csslint-wsh.js index 0549e622..bc1b9085 100644 --- a/dist/csslint-wsh.js +++ b/dist/csslint-wsh.js @@ -9378,7 +9378,7 @@ CSSLint.addRule({ // rule information id: "outline-none", name: "Disallow outline: none", - desc: "Use of outline: none or outline: 0 should be limited to :focus rules.", + desc: "Use of outline: none | 0 | transparent should be limited to :focus rules and resulting elements should be visible.", url: "https://github.com/CSSLint/csslint/wiki/Disallow-outline%3Anone", browsers: "All", tags: ["Accessibility"], @@ -9396,7 +9396,8 @@ CSSLint.addRule({ col: event.col, selectors: event.selectors, propCount: 0, - outline: false + outline: false, + potentiallyInvisibleElement: false }; } else { lastRule = null; @@ -9408,7 +9409,7 @@ CSSLint.addRule({ if (lastRule.outline) { if (lastRule.selectors.toString().toLowerCase().indexOf(":focus") === -1) { reporter.report("Outlines should only be modified using :focus.", lastRule.line, lastRule.col, rule); - } else if (lastRule.propCount === 1) { + } else if (lastRule.propCount === 1 || lastRule.potentiallyInvisibleElement === true) { reporter.report("Outlines shouldn't be hidden unless other visual changes are made.", lastRule.line, lastRule.col, rule); } } @@ -9423,13 +9424,23 @@ CSSLint.addRule({ parser.addListener("startviewport", startRule); parser.addListener("property", function(event) { + var name = event.property.text.toLowerCase(), - value = event.value; + valueString = event.value.toString().toLowerCase(); if (lastRule) { lastRule.propCount++; - if (name === "outline" && (value.toString() === "none" || value.toString() === "0")) { - lastRule.outline = true; + + if (valueString.indexOf("none") !== -1 || valueString.indexOf("0") !== -1 || valueString.indexOf("transparent") !== -1) { + if (name === "outline") { + lastRule.outline = true; + } + else { + // these properties must not be 0, none, or transparent when outline is already one of those values + if (name.indexOf("border") >= 0) { + lastRule.potentiallyInvisibleElement = true; + } + } } } diff --git a/dist/csslint.js b/dist/csslint.js index cc06b7ce..f2a9a646 100644 --- a/dist/csslint.js +++ b/dist/csslint.js @@ -9378,7 +9378,7 @@ CSSLint.addRule({ // rule information id: "outline-none", name: "Disallow outline: none", - desc: "Use of outline: none or outline: 0 should be limited to :focus rules.", + desc: "Use of outline: none | 0 | transparent should be limited to :focus rules and resulting elements should be visible.", url: "https://github.com/CSSLint/csslint/wiki/Disallow-outline%3Anone", browsers: "All", tags: ["Accessibility"], @@ -9396,7 +9396,8 @@ CSSLint.addRule({ col: event.col, selectors: event.selectors, propCount: 0, - outline: false + outline: false, + potentiallyInvisibleElement: false }; } else { lastRule = null; @@ -9408,7 +9409,7 @@ CSSLint.addRule({ if (lastRule.outline) { if (lastRule.selectors.toString().toLowerCase().indexOf(":focus") === -1) { reporter.report("Outlines should only be modified using :focus.", lastRule.line, lastRule.col, rule); - } else if (lastRule.propCount === 1) { + } else if (lastRule.propCount === 1 || lastRule.potentiallyInvisibleElement === true) { reporter.report("Outlines shouldn't be hidden unless other visual changes are made.", lastRule.line, lastRule.col, rule); } } @@ -9423,13 +9424,23 @@ CSSLint.addRule({ parser.addListener("startviewport", startRule); parser.addListener("property", function(event) { + var name = event.property.text.toLowerCase(), - value = event.value; + valueString = event.value.toString().toLowerCase(); if (lastRule) { lastRule.propCount++; - if (name === "outline" && (value.toString() === "none" || value.toString() === "0")) { - lastRule.outline = true; + + if (valueString.indexOf("none") !== -1 || valueString.indexOf("0") !== -1 || valueString.indexOf("transparent") !== -1) { + if (name === "outline") { + lastRule.outline = true; + } + else { + // these properties must not be 0, none, or transparent when outline is already one of those values + if (name.indexOf("border") >= 0) { + lastRule.potentiallyInvisibleElement = true; + } + } } } diff --git a/src/rules/outline-none.js b/src/rules/outline-none.js index da7b4e8a..135b0fd5 100644 --- a/src/rules/outline-none.js +++ b/src/rules/outline-none.js @@ -8,7 +8,7 @@ CSSLint.addRule({ // rule information id: "outline-none", name: "Disallow outline: none", - desc: "Use of outline: none or outline: 0 should be limited to :focus rules.", + desc: "Use of outline: none | 0 | transparent should be limited to :focus rules and resulting elements should be visible.", url: "https://github.com/CSSLint/csslint/wiki/Disallow-outline%3Anone", browsers: "All", tags: ["Accessibility"], @@ -26,7 +26,8 @@ CSSLint.addRule({ col: event.col, selectors: event.selectors, propCount: 0, - outline: false + outline: false, + potentiallyInvisibleElement: false }; } else { lastRule = null; @@ -38,7 +39,7 @@ CSSLint.addRule({ if (lastRule.outline) { if (lastRule.selectors.toString().toLowerCase().indexOf(":focus") === -1) { reporter.report("Outlines should only be modified using :focus.", lastRule.line, lastRule.col, rule); - } else if (lastRule.propCount === 1) { + } else if (lastRule.propCount === 1 || lastRule.potentiallyInvisibleElement === true) { reporter.report("Outlines shouldn't be hidden unless other visual changes are made.", lastRule.line, lastRule.col, rule); } } @@ -53,13 +54,23 @@ CSSLint.addRule({ parser.addListener("startviewport", startRule); parser.addListener("property", function(event) { + var name = event.property.text.toLowerCase(), - value = event.value; + valueString = event.value.toString().toLowerCase(); if (lastRule) { lastRule.propCount++; - if (name === "outline" && (value.toString() === "none" || value.toString() === "0")) { - lastRule.outline = true; + + if (valueString.indexOf("none") !== -1 || valueString.indexOf("0") !== -1 || valueString.indexOf("transparent") !== -1) { + if (name === "outline") { + lastRule.outline = true; + } + else { + // these properties must not be 0, none, or transparent when outline is already one of those values + if (name.indexOf("border") >= 0) { + lastRule.potentiallyInvisibleElement = true; + } + } } } diff --git a/tests/rules/outline-none.js b/tests/rules/outline-none.js index 4ac4e8f3..c5ae6297 100644 --- a/tests/rules/outline-none.js +++ b/tests/rules/outline-none.js @@ -13,6 +13,13 @@ Assert.areEqual("Outlines should only be modified using :focus.", result.messages[0].message); }, + "Using outline: transparent should result in a warning": function() { + var result = CSSLint.verify(".foo { outline: transparent}", { "outline-none": 1 }); + Assert.areEqual(1, result.messages.length); + Assert.areEqual("warning", result.messages[0].type); + Assert.areEqual("Outlines should only be modified using :focus.", result.messages[0].message); + }, + "Using outline: 0 should result in a warning": function() { var result = CSSLint.verify(".foo { outline: 0; }", { "outline-none": 1 }); Assert.areEqual(1, result.messages.length); @@ -34,16 +41,55 @@ Assert.areEqual("Outlines shouldn't be hidden unless other visual changes are made.", result.messages[0].message); }, - "Using outline: none with :focus and another property should not result in a warning": function() { + "Using outline: transparent alone with :focus should result in a warning": function() { + var result = CSSLint.verify(".foo:focus { outline: transparent; }", { "outline-none": 1 }); + Assert.areEqual(1, result.messages.length); + Assert.areEqual("warning", result.messages[0].type); + Assert.areEqual("Outlines shouldn't be hidden unless other visual changes are made.", result.messages[0].message); + }, + + "Using outline: none with :focus and another visible property should not result in a warning": function() { var result = CSSLint.verify(".foo:focus { outline: none; border: 1px solid black; }", { "outline-none": 1 }); Assert.areEqual(0, result.messages.length); }, - "Using outline: 0 with :focus and another property should not result in a warning": function() { + "Using outline: 0 with :focus and another visible property should not result in a warning": function() { var result = CSSLint.verify(".foo:focus { outline: 0; border: 1px solid black;}", { "outline-none": 1 }); Assert.areEqual(0, result.messages.length); - } + }, + + "Using outline: 1px solid transparent; with :focus should result in a warning": function() { + var result = CSSLint.verify(".foo:focus { outline: 1px solid transparent;}", { "outline-none": 1 }); + Assert.areEqual(1, result.messages.length); + Assert.areEqual("warning", result.messages[0].type); + Assert.areEqual("Outlines shouldn't be hidden unless other visual changes are made.", result.messages[0].message); + }, + "Using outline: 0 with :focus and another transparent property should result in a warning": function() { + var result = CSSLint.verify(".foo:focus { outline: 0; border: 1px solid transparent;}", { "outline-none": 1 }); + Assert.areEqual(1, result.messages.length); + Assert.areEqual("warning", result.messages[0].type); + Assert.areEqual("Outlines shouldn't be hidden unless other visual changes are made.", result.messages[0].message); + }, + + "Using outline: 0 with :focus and another zeroed property should result in a warning": function() { + var result = CSSLint.verify(".foo:focus { outline: 0; border: 0 solid black;}", { "outline-none": 1 }); + Assert.areEqual(1, result.messages.length); + Assert.areEqual("warning", result.messages[0].type); + Assert.areEqual("Outlines shouldn't be hidden unless other visual changes are made.", result.messages[0].message); + }, + + "Using outline: 0 red; with :focus should result in a warning": function() { + var result = CSSLint.verify(".foo:focus { outline: 0 red;}", { "outline-none": 1 }); + Assert.areEqual(1, result.messages.length); + Assert.areEqual("warning", result.messages[0].type); + Assert.areEqual("Outlines shouldn't be hidden unless other visual changes are made.", result.messages[0].message); + }, + + "Using outline: 0 with :focus and another zeroed property that does not affect rendering should not result in a warning": function() { + var result = CSSLint.verify(".foo:focus { outline: 0; margin: 0;}", { "outline-none": 1 }); + Assert.areEqual(0, result.messages.length); + } })); })();