-
-
Notifications
You must be signed in to change notification settings - Fork 167
/
units_zero.sql
118 lines (108 loc) · 3.09 KB
/
units_zero.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
#standardSQL
CREATE TEMPORARY FUNCTION getZeroUnits(css STRING)
RETURNS ARRAY<STRUCT<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.zeroes).map(([unit, freq]) => {
return {unit, freq}
});
} catch (e) {
return [];
}
''';
SELECT
*
FROM (
SELECT
client,
unit.unit,
COUNT(DISTINCT page) AS pages,
SUM(unit.freq) AS freq,
SUM(SUM(unit.freq)) OVER (PARTITION BY client) AS total,
SUM(unit.freq) / SUM(SUM(unit.freq)) OVER (PARTITION BY client) AS pct
FROM
`httparchive.almanac.parsed_css`,
UNNEST(getZeroUnits(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)
WHERE
freq >= 1000
ORDER BY
pct DESC