Skip to content

Commit 18419e3

Browse files
committed
🌅
0 parents  commit 18419e3

24 files changed

+1565
-0
lines changed

‎.eslintrc.js

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
module.exports = {
2+
rules: {
3+
indent: [
4+
2, 2
5+
],
6+
quotes: [
7+
2,
8+
"single",
9+
"avoid-escape"
10+
],
11+
"linebreak-style": [
12+
2,
13+
"unix"
14+
],
15+
semi: [
16+
2,
17+
"never"
18+
],
19+
"no-trailing-spaces": [2]
20+
},
21+
parserOptions: {
22+
ecmaVersion: 6,
23+
sourceType: "module"
24+
},
25+
ecmaFeatures: {
26+
modules: true
27+
},
28+
sourceType: "module",
29+
env: {
30+
es6: true,
31+
node: true,
32+
browser: true
33+
},
34+
extends: "eslint:recommended"
35+
}

‎.gitignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
upstream/prefixfree
2+
node_modules

‎README.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
# j2c-filter-prefix
2+
3+
This is much WIP, probably broken, but it's been

‎TODO.md

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
### Figure a way to reliably prefix pixel-ratio
2+
3+
var mq = window.matchMedia( "(min-width: 500px)" );
4+
5+
The matches property returns true or false depending on the query result, e.g.
6+
7+
if (mq.matches) {
8+
// window width is at least 500px
9+
} else {
10+
// window width is less than 500px
11+
}
12+
13+
### PostCSS-based server-side plugin.

‎dist/j2c-plugin-prefix.amd.js

Lines changed: 315 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,315 @@
1+
define(function () { 'use strict';
2+
3+
var self$1 = {}
4+
var root = document.documentElement
5+
6+
var prefixes = {};
7+
var properties$1 = [];
8+
var style = getComputedStyle(document.documentElement, null);
9+
var dummy = document.createElement('div').style;
10+
var iterate = function(property) {
11+
if(property.charAt(0) === '-') {
12+
properties$1.push(property);
13+
14+
var parts = property.split('-'),
15+
prefix = parts[1];
16+
17+
// Count prefix uses
18+
prefixes[prefix] = ++prefixes[prefix] || 1;
19+
20+
// This helps determining shorthands
21+
while(parts.length > 3) {
22+
parts.pop();
23+
24+
var shorthand = parts.join('-');
25+
26+
if(supported(shorthand) && properties$1.indexOf(shorthand) === -1) {
27+
properties$1.push(shorthand);
28+
}
29+
}
30+
}
31+
};
32+
var supported = function(property) {
33+
return StyleFix.camelCase(property) in dummy;
34+
};
35+
// Some browsers have numerical indices for the properties, some don't
36+
if(style && style.length > 0) {
37+
for(var i=0; i<style.length; i++) {
38+
iterate(style[i])
39+
}
40+
}
41+
else {
42+
for(var property in style) {
43+
iterate(StyleFix.deCamelCase(property));
44+
}
45+
}
46+
// Find most frequently used prefix
47+
var highest = {uses:0};
48+
for(var prefix$1 in prefixes) {
49+
var uses = prefixes[prefix$1];
50+
51+
if(highest.uses < uses) {
52+
highest = {prefix: prefix$1, uses: uses};
53+
}
54+
}
55+
self$1.prefix = '-' + highest.prefix + '-';
56+
self$1.Prefix = StyleFix.camelCase(self$1.prefix);
57+
self$1.properties = [];
58+
// Get properties ONLY supported with a prefix
59+
for(var i=0; i<properties$1.length; i++) {
60+
var property = properties$1[i];
61+
62+
if(property.indexOf(self$1.prefix) === 0) { // we might have multiple prefixes, like Opera
63+
var unprefixed = property.slice(self$1.prefix.length);
64+
65+
if(!supported(unprefixed)) {
66+
self$1.properties.push(unprefixed);
67+
}
68+
}
69+
}
70+
// IE fix
71+
if(self$1.Prefix == 'Ms'
72+
&& !('transform' in dummy)
73+
&& !('MsTransform' in dummy)
74+
&& ('msTransform' in dummy)) {
75+
self$1.properties.push('transform', 'transform-origin');
76+
}
77+
self$1.properties.sort();
78+
79+
// Values that might need prefixing
80+
var functions = {
81+
'linear-gradient': {
82+
property: 'backgroundImage',
83+
params: 'red, teal'
84+
},
85+
'calc': {
86+
property: 'width',
87+
params: '1px + 5%'
88+
},
89+
'element': {
90+
property: 'backgroundImage',
91+
params: '#foo'
92+
},
93+
'cross-fade': {
94+
property: 'backgroundImage',
95+
params: 'url(a.png), url(b.png), 50%'
96+
}
97+
};
98+
functions['repeating-linear-gradient'] =
99+
functions['repeating-radial-gradient'] =
100+
functions['radial-gradient'] =
101+
functions['linear-gradient'];
102+
// Note: The properties assigned are just to *test* support.
103+
// The keywords will be prefixed everywhere.
104+
var keywords = {
105+
'initial': 'color',
106+
'zoom-in': 'cursor',
107+
'zoom-out': 'cursor',
108+
'box': 'display',
109+
'flexbox': 'display',
110+
'inline-flexbox': 'display',
111+
'flex': 'display',
112+
'inline-flex': 'display',
113+
'grid': 'display',
114+
'inline-grid': 'display',
115+
'max-content': 'width',
116+
'min-content': 'width',
117+
'fit-content': 'width',
118+
'fill-available': 'width'
119+
};
120+
self$1.functions = [];
121+
self$1.keywords = [];
122+
var style$1 = document.createElement('div').style;
123+
function supported$1(value, property) {
124+
style$1[property] = '';
125+
style$1[property] = value;
126+
127+
return !!style$1[property];
128+
}
129+
for (var func in functions) {
130+
var test = functions[func],
131+
property = test.property,
132+
value = func + '(' + test.params + ')';
133+
134+
if (!supported$1(value, property)
135+
&& supported$1(self$1.prefix + value, property)) {
136+
// It's supported, but with a prefix
137+
self$1.functions.push(func);
138+
}
139+
}
140+
for (var keyword in keywords) {
141+
var property$1 = keywords[keyword];
142+
143+
if (!supported$1(keyword, property$1)
144+
&& supported$1(self$1.prefix + keyword, property$1)) {
145+
// It's supported, but with a prefix
146+
self$1.keywords.push(keyword);
147+
}
148+
}
149+
150+
var selectors = {
151+
':read-only': null,
152+
':read-write': null,
153+
':any-link': null,
154+
'::selection': null
155+
};
156+
var atrules = {
157+
'keyframes': 'name',
158+
'viewport': null,
159+
'document': 'regexp(".")'
160+
};
161+
self$1.selectors = [];
162+
self$1.atrules = [];
163+
var style$2 = root.appendChild(document.createElement('style'));
164+
function supported$2(selector) {
165+
style$2.textContent = selector + '{}'; // Safari 4 has issues with style.innerHTML
166+
167+
return !!style$2.sheet.cssRules.length;
168+
}
169+
for(var selector in selectors) {
170+
var test = selector + (selectors[selector]? '(' + selectors[selector] + ')' : '');
171+
172+
if(!supported$2(test) && supported$2(self$1.prefixSelector(test))) {
173+
self$1.selectors.push(selector);
174+
}
175+
}
176+
for(var atrule in atrules) {
177+
var test$1 = atrule + ' ' + (atrules[atrule] || '');
178+
179+
if(!supported$2('@' + test$1) && supported$2('@' + self$1.prefix + test$1)) {
180+
self$1.atrules.push(atrule);
181+
}
182+
}
183+
root.removeChild(style$2);
184+
185+
// Properties that accept properties as their value
186+
self$1.valueProperties = [
187+
'transition',
188+
'transition-property',
189+
'will-change'
190+
]
191+
// Add class for current prefix
192+
root.className += ' ' + self$1.prefix;
193+
194+
// decorate the fixers object.
195+
var own = {}.hasOwnProperty
196+
197+
function setify(ary){
198+
var res = {}
199+
ary.forEach(function(p) {res[p] = true})
200+
return res
201+
}
202+
203+
var prefix = target.prefix
204+
205+
var replacerString = '$&'+prefix
206+
207+
atRulesSet = setify(target.atrules.map(function(r){return '@'+r}))
208+
209+
var atRulesMatcher = new RegExp('^@('+target.atrules.join('|')+')\\b')
210+
var atRulesReplacer = '@' + prefix + '$1'
211+
212+
function makeDetector (before, targets, after) {
213+
return new Regexp(before + '(?:' + targets.join('|') + ')' + after)
214+
}
215+
216+
function makeLexer (before, targets, after) {
217+
new RegExp(
218+
"\"(?:\\\\[\\S\\s]|[^\"])*\"|'(?:\\\\[\\S\\s]|[^'])*'|\\/\\*[\\S\\s]*?\\*\\/|" +
219+
before + '((?:' +
220+
targets.join('|') +
221+
')' + after + ')',
222+
'gi'
223+
)
224+
}
225+
226+
function replacer (match, $1, $2) {
227+
if (!$1) return match
228+
return $1 + prefix + $2
229+
}
230+
231+
var selectorMatcher = makeLexer("\\b(", target.selectors, ")\\b")
232+
var selectorReplacer = makeReplacer(/^::?/, replacerString)
233+
234+
var propertiesSet = setify(target.properties)
235+
target.properties.forEach(function(p) {properties[p] = true})
236+
237+
238+
// If this were ever updated, verify that the next comment is still valid.
239+
var valueProperties = {
240+
'transition': 1,
241+
'transition-property': 1
242+
}
243+
244+
// value = fix('functions', '(^|\\s|,)', '\\s*\\(', '$1' + self.prefix + '$2(', value);
245+
var convertFunctions = !!target.functions.length
246+
var functionsDetector = makeDetector("(?:^|\\s|,)", target.fuctions, '\\s*\\(')
247+
var functionsMatcher = makeLexer("(^|\\s|,)", target.fuctions, '\\s*\\(')
248+
249+
// value = fix('keywords', '(^|\\s)', '(\\s|$)', '$1' + self.prefix + '$2$3', value);
250+
var convertKeywords = !!target.keywords.length
251+
var keywordsDetector = makeDetector("(?:^|\\s)", target.keywords, '(?:\\s|$)')
252+
var keywordsMatcher = makeLexer("(^|\\s)", target.keywords, '(?:\\s|$)')
253+
254+
// No need to look for strings in these properties. We may insert prefixes in comments. Oh the humanity.
255+
// value = fix('properties', '(^|\\s|,)', '($|\\s|,)', '$1'+self.prefix+'$2$3', value);
256+
var convertProperties = !!target.properties.length
257+
var valuePropertiesDetector = makeDetector('(?:^|\\s|,)', target.properties, '(?:$|\\s|,)')
258+
var valuePropertiesMatcher = new RegExp('(^|\\s|,)((?:' + target.properties.join('|') + ')(?:$|\\s|,))','gi')
259+
var valuePropertiesReplacer = '$1' + target.prefix + '$2'
260+
261+
// Gradients are supported with a prefix, convert angles to legacy
262+
var convertGradients = self.functions.indexOf('linear-gradient') > -1
263+
function fixValue (value, property) {
264+
if (convertFunctions && functionsDetector.test(value)) value = value.replace(functionsMatcher, replacer)
265+
if (convertKeywords && keywordsDetector.test(value)) value = value.replace(keywordsMatcher, replacer)
266+
267+
if (convertProperties && own.call(valueProperties, property) && valuePropertiesDetector.test(value)) {
268+
value = value.replace(valuePropertiesMatcher, valuePropertiesReplacer)
269+
}
270+
return value;
271+
}
272+
273+
function prefixPlugin(j2c) {
274+
if(window.addEventListener) {
275+
return {
276+
$filter: function(next) {
277+
var atStack = []
278+
return {
279+
i: function() {
280+
next.i()
281+
atStack.length = 0
282+
},
283+
a: function(rule, params, hasBlock) {
284+
rule = own.call(atRulesSet, rule) ? rule.replace(atRulesMatcher, atRulesReplacer) : rule
285+
if (hasBlock) atStack.push(rule)
286+
next.a(
287+
rule,
288+
params,
289+
hasBlock
290+
)
291+
},
292+
A: function() {
293+
next.A(atStack.pop())
294+
},
295+
d: function(property, value){
296+
next.d(
297+
own.call(propertiesSet, property) ? prefix + property : property,
298+
colon,
299+
fixValue(value, property),
300+
semi
301+
)
302+
},
303+
s: function(selector, brace) {
304+
if (selectorMatcher.test(selector)) selector = selector.replace(selectorMatcher, selectorReplacer)
305+
next.s(selector, brace)
306+
}
307+
}
308+
}
309+
}
310+
}
311+
}
312+
313+
return prefixPlugin;
314+
315+
});

‎dist/j2c-plugin-prefix.amd.min.js

Lines changed: 1 addition & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)