Fix #25 scoper pesudo issue

This commit is contained in:
xcatliu 2017-03-22 14:22:10 +08:00
parent 91adc77775
commit 7225ea0487
2 changed files with 122 additions and 72 deletions

View File

@ -1,50 +1,53 @@
import Omi from './omi.js'
//many thanks to https://github.com/thomaspark/scoper/
function scoper(css, prefix) {
let re = new RegExp("([^\r\n,{}]+)(,(?=[^}]*{)|\s*{)", "g")
css = css.replace(re, function(g0, g1, g2) {
if (g1.match(/^\s*(@media|@keyframes|to|from|@font-face)/)) {
return g1 + g2
}
if (g1.match(/:scope/)) {
g1 = g1.replace(/([^\s]*):scope/, function (h0, h1) {
if (h1 === "") {
return "> *"
} else {
return "> " + h1
}
})
}
g1 = g1.replace(/^(\s*)/, g1.trim() + prefix + "," + "$1" + prefix + " ").replace(/\s+/g, ' ')
return g1 + g2
})
return css
}
function addStyle(cssText, id) {
let ele = document.getElementById(Omi.STYLEPREFIX + id),
head = document.getElementsByTagName('head')[0]
if (ele && ele.parentNode === head) {
head.removeChild(ele)
}
let someThingStyles = document.createElement('style')
head.appendChild(someThingStyles)
someThingStyles.setAttribute('type', 'text/css')
someThingStyles.setAttribute('id',Omi.STYLEPREFIX + id)
if (!!window.ActiveXObject) {
someThingStyles.styleSheet.cssText = cssText
} else {
someThingStyles.textContent = cssText
}
}
export default {
scoper:scoper,
addStyle:addStyle
import Omi from './omi.js'
//many thanks to https://github.com/thomaspark/scoper/
function scoper(css, prefix) {
let re = new RegExp("([^\r\n,{}:]+)(:[^\r\n,{}]+)?(,(?=[^{]*{)|\s*{)", "g")
/**
* Example:
*
* .classname::pesudo { color:red }
*
* g1 is normal selector `.classname`
* g2 is pesudo class or pesudo element
* g3 is the suffix
*/
css = css.replace(re, function(g0, g1, g2, g3) {
if (typeof g2 === "undefined") {
g2 = "";
}
if (g1.match(/^\s*(@media|@keyframes|to|from|@font-face)/)) {
return g1 + g2 + g3
}
var appendClass = g1.replace(/(\s*)$/, "") + prefix + g2
var prependClass = prefix + " " + g1.trim() + g2;
return appendClass + "," + prependClass + g3
})
return css
}
function addStyle(cssText, id) {
let ele = document.getElementById(Omi.STYLEPREFIX + id),
head = document.getElementsByTagName('head')[0]
if (ele && ele.parentNode === head) {
head.removeChild(ele)
}
let someThingStyles = document.createElement('style')
head.appendChild(someThingStyles)
someThingStyles.setAttribute('type', 'text/css')
someThingStyles.setAttribute('id',Omi.STYLEPREFIX + id)
if (!!window.ActiveXObject) {
someThingStyles.styleSheet.cssText = cssText
} else {
someThingStyles.textContent = cssText
}
}
export default {
scoper:scoper,
addStyle:addStyle
}

View File

@ -1,29 +1,76 @@
import assert from 'assert';
import style from '../../src/style.js';
describe("scoper", function() {
describe("Attribute selector as prefix", function() {
var result = style.scoper(".active{ color:red};","[attribute]");
it("expect attribute selector prefix works well", function() {
expect(result).toBe(".active[attribute],[attribute] .active{ color:red};");
});
});
var result = style.scoper(".active{ color:red};","[ab12]")
it("and so is a spec", function() {
expect(result).toBe(".active[ab12],[ab12] .active{ color:red};");
});
});
describe("scoper-ml", function() {
var result = style.scoper(".active{ " +
"color:red" +
"};","#test")
it("and so is a spec", function() {
expect(result).toBe(".active#test,#test .active{ " +
"color:red" +
"};");
});
});
describe("scoper3", function() {
var result = style.scoper(".active,.xx{ color:red};","#ab12")
it("and so is a spec", function() {
expect(result).toBe(".active#ab12,#ab12 .active,.xx#ab12,#ab12 .xx{ color:red};");
describe("Id selector as prefix", function() {
var result = style.scoper(".active{ color:red};","#id");
it("expect id selector prefix works well", function() {
expect(result).toBe(".active#id,#id .active{ color:red};");
});
});
describe("Two classes", function() {
var result = style.scoper(".active,.xx{ color:red};","#id");
it("expect id selector prefix works well with two class selector", function() {
expect(result).toBe(".active#id,#id .active,.xx#id,#id .xx{ color:red};");
});
});
describe("Pseudo class", function() {
var result = style.scoper(".active:hover{ color:red};","[attribute]");
it("expect pseudo class works well", function() {
expect(result).toBe(".active[attribute]:hover,[attribute] .active:hover{ color:red};");
});
});
describe("Pseudo element", function() {
var result = style.scoper(".active::after{ color:red};","[attribute]");
it("expect pseudo element works well", function() {
expect(result).toBe(".active[attribute]::after,[attribute] .active::after{ color:red};");
});
});
describe("Quoted values", function() {
var result = style.scoper(".active { font-family: \"Helvetica Neue\"};","[attribute]");
it("expect quoted values works well", function() {
expect(result).toBe(".active[attribute],[attribute] .active{ font-family: \"Helvetica Neue\"};");
});
});
describe("Media queries", function() {
var rule = "@media (max-width: 600px) {\n" +
" h1 {\n" +
" font-family: \"Helvetica Neue\", Helvetica, Arial, sans-serif;\n" +
" }" +
"}";
var expected = "@media (max-width: 600px) {\n" +
" h1#scoper-1,#scoper-1 h1{\n" +
" font-family: \"Helvetica Neue\", Helvetica, Arial, sans-serif;\n" +
" }" +
"}";
var actual = style.scoper(rule, "#scoper-1");
it("expect media queries works well", function() {
expect(actual).toBe(expected);
});
});
describe("Font faces", function() {
var rule = "@font-face {\n" +
" font-family: 'MyWebFont';\n" +
" src: url('myfont.woff2') format('woff2');\n" +
" url('myfont.woff') format('woff');\n" +
"}";
var expected = rule;
var actual = style.scoper(rule, "#scoper-1");
it("expect font faces works well", function() {
expect(actual).toBe(expected);
});
});
});