Skip to content

Commit 897d645

Browse files
authored
Add SQL function to analyze custom property depths
1 parent 27604e0 commit 897d645

File tree

1 file changed

+125
-0
lines changed

1 file changed

+125
-0
lines changed
Lines changed: 125 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,125 @@
1+
#standardSQL
2+
CREATE TEMPORARY FUNCTION getCustomPropertyLengths(vars JSON)
3+
RETURNS ARRAY<STRUCT<depth INT64, freq INT64>>
4+
LANGUAGE js
5+
OPTIONS (library = "gs://httparchive/lib/css-utils.js")
6+
AS '''
7+
try {
8+
function compute(vars) {
9+
function walkElements(node, callback, parent) {
10+
if (Array.isArray(node)) {
11+
for (let n of node) {
12+
walkElements(n, callback, parent);
13+
}
14+
}
15+
else {
16+
callback(node, parent);
17+
18+
if (node.children) {
19+
walkElements(node.children, callback, node);
20+
}
21+
}
22+
}
23+
24+
let ret = {
25+
depths: {}
26+
};
27+
28+
function countDependencyLength(node, property) {
29+
if (!node) {
30+
return 0;
31+
}
32+
33+
let declarations = node.declarations;
34+
35+
if (!declarations || !(property in declarations)) {
36+
return countDependencyLength(node.parent, property);
37+
}
38+
39+
let o = declarations[property];
40+
41+
if (!o.references || o.references.length === 0) {
42+
return 0;
43+
}
44+
45+
let lengths = o.references.map(p => countDependencyLength(node, p));
46+
47+
return 1 + Math.max(...lengths);
48+
}
49+
50+
walkElements(vars.computed, (node, parent) => {
51+
if (parent && !node.parent) {
52+
node.parent = parent;
53+
}
54+
55+
if (node.declarations) {
56+
for (let property in node.declarations) {
57+
58+
let o = node.declarations[property];
59+
if (o.computed && o.computed.trim() !== o.value.trim() && (o.computed === "initial" || o.computed === "null")) {
60+
// Cycle or missing ref
61+
incrementByKey(ret, "cycles_or_initial");
62+
}
63+
else {
64+
let depth = countDependencyLength(node, property);
65+
66+
incrementByKey(ret.depths, depth);
67+
}
68+
}
69+
}
70+
});
71+
72+
return ret;
73+
}
74+
if (!vars || !vars.computed) return null;
75+
var custom_props = compute(vars);
76+
return Object.entries(custom_props.depths).map(([depth, freq]) => ({depth, freq}))
77+
} catch (e) {
78+
return [];
79+
}
80+
''';
81+
82+
WITH totals AS (
83+
SELECT
84+
client,
85+
COUNT(0) AS total_pages
86+
FROM
87+
`httparchive.crawl.pages`
88+
WHERE
89+
date = '2025-07-01' AND
90+
is_root_page
91+
GROUP BY
92+
client
93+
)
94+
95+
SELECT
96+
client,
97+
depth,
98+
COUNT(DISTINCT page) AS pages,
99+
ANY_VALUE(total_pages) AS total_pages,
100+
COUNT(DISTINCT page) / ANY_VALUE(total_pages) AS pct_pages,
101+
SUM(freq) AS freq,
102+
SUM(SUM(freq)) OVER (PARTITION BY client) AS total,
103+
SUM(freq) / SUM(SUM(freq)) OVER (PARTITION BY client) AS pct
104+
FROM (
105+
SELECT
106+
client,
107+
page,
108+
custom_properties.depth,
109+
custom_properties.freq
110+
FROM
111+
`httparchive.crawl.pages`,
112+
UNNEST(getCustomPropertyLengths(custom_metrics.css_variables)) AS custom_properties
113+
WHERE
114+
date = '2025-07-01' AND
115+
is_root_page
116+
)
117+
JOIN
118+
totals
119+
USING (client)
120+
GROUP BY
121+
client,
122+
depth
123+
ORDER BY
124+
depth,
125+
client

0 commit comments

Comments
 (0)