-
-
Notifications
You must be signed in to change notification settings - Fork 167
/
units_properties.sql
131 lines (121 loc) · 3.38 KB
/
units_properties.sql
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
#standardSQL
CREATE TEMPORARY FUNCTION getPropertyUnits(css STRING)
RETURNS ARRAY<STRUCT<property STRING, unit STRING, freq INT64>>
LANGUAGE js
OPTIONS (library = "gs://httparchive/lib/css-utils.js")
AS '''
try {
function compute(ast) {
let ret = {
zeroes: {},
by_property: {}
};
const lengths = /(?<![-#\\w])\\b(?<number>-?\\d*\\.?\\d+)(?<unit>%|[a-z]{1,4}\\b|(?=\\s|$|,|\\*|\\/)\\b)/gi;
walkDeclarations(ast, ({property, value}) => {
// Remove color functions to avoid mucking results
value = removeFunctionCalls(value, {names: ["rgb", "rgba", "hsl", "hsla"]});
for (let length of value.matchAll(lengths)) {
let {number, unit} = length.groups;
ret.by_property[property] = ret.by_property[property] || {};
if (number === "0") {
incrementByKey(ret.zeroes, unit || "<number>");
}
if (unit) {
incrementByKey(ret, unit);
incrementByKey(ret.by_property[property], unit);
}
else {
incrementByKey(ret, "<number>");
incrementByKey(ret.by_property[property], "<number>");
}
incrementByKey(ret, "total"); // for calculating %
incrementByKey(ret.by_property[property], "total"); // for calculating %
}
}, {
// Properties that take one or more lengths
// We avoid shorthands because they're a mess to parse
// This helped: https://codepen.io/leaverou/pen/rNergbW?editors=0010
properties: [
"baseline-shift",
"box-shadow",
"vertical-align",
"clip-path",
/^column[s-]|^inset\b/g,
"contain-intrinsic-size",
"cx",
"cy",
"flex-basis",
"letter-spacing",
"perspective",
"perspective-origin",
"r",
"row-gap",
"rx",
"ry",
"tab-size",
"text-indent",
"text-shadow",
"translate",
"vertical-align",
"word-spacing",
"x",
"y",
/\\b(?:width|height|thickness|offset|origin|padding|border|margin|outline|top|right|bottom|left|(inline|block)-(start|end)|gap|size|position)\\b/g
],
not: {
// Drop prefixed properties and custom properties
properties: /^-|-color$/
}
});
ret = sortObject(ret);
for (let property in ret.by_property) {
ret.by_property[property] = sortObject(ret.by_property[property]);
}
return ret;
}
var ast = JSON.parse(css);
var units = compute(ast);
return Object.entries(units.by_property).flatMap(([property, units]) => {
return Object.entries(units).filter(([unit]) => {
return unit != 'total';
}).map(([unit, freq]) => {
return {property, unit, freq};
});
});
} catch (e) {
return [];
}
''';
SELECT
*
FROM (
SELECT
client,
property,
unit,
SUM(freq) AS freq,
SUM(SUM(freq)) OVER (PARTITION BY client, property) AS total,
SUM(freq) / SUM(SUM(freq)) OVER (PARTITION BY client, property) AS pct
FROM (
SELECT
client,
unit.property,
unit.unit,
unit.freq
FROM
`httparchive.almanac.parsed_css`,
UNNEST(getPropertyUnits(css)) AS unit
WHERE
date = '2021-07-01' AND
# Limit the size of the CSS to avoid OOM crashes.
LENGTH(css) < 0.1 * 1024 * 1024)
GROUP BY
client,
unit,
property)
WHERE
total >= 1000 AND
pct >= 0.01
ORDER BY
total DESC,
pct DESC