Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
96 changes: 96 additions & 0 deletions scripts/check-dead-html-visual.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
import { chromium } from 'playwright';
import sharp from 'sharp';
import { mkdirSync, writeFileSync } from 'node:fs';
import { resolve } from 'node:path';

const [beforeUrl, afterUrl] = process.argv.slice(2);
if (!beforeUrl || !afterUrl) {
console.error('Usage: node scripts/check-dead-html-visual.mjs <before-url> <after-url>');
process.exit(2);
}

const routes = [
'/', '/shop', '/shop/comma-four', '/shop/chestnut', '/shop/body',
'/shop/comma-four-trade-in', '/vehicles', '/openpilot', '/setup',
'/support', '/jobs', '/connect', '/media', '/terms', '/neurips.html',
'/leaderboard.html', '/harness-parts.html',
];
const viewports = [390, 1440];
const outputDirectory = resolve('/tmp/dead-html-visual');
const browser = await chromium.launch({ headless: true });
const failures = [];
mkdirSync(outputDirectory, { recursive: true });

async function capture(url, route, width) {
const page = await browser.newPage({
viewport: { width, height: 900 },
deviceScaleFactor: 1,
reducedMotion: 'reduce',
});

await page.addInitScript(() => {
const fixedTime = Date.parse('2026-11-01T00:00:00Z');
Date.now = () => fixedTime;
});
await page.route('**/*', (request) => {
const requestHost = new URL(request.request().url()).hostname;
return requestHost === '127.0.0.1' || requestHost === 'localhost'
? request.continue()
: request.abort();
});

const response = await page.goto(new URL(route, url).href, {
waitUntil: 'domcontentloaded',
timeout: 30_000,
}).catch(() => null);
await page.evaluate(() => {
document.querySelectorAll('img[loading="lazy"]').forEach((image) => {
image.loading = 'eager';
});
});
await page.waitForFunction(
() => [...document.images].every((image) => image.complete),
null,
{ timeout: 5_000 },
).catch(() => {});
await page.evaluate(() => document.fonts.ready);
await page.addStyleTag({
content: 'video{visibility:hidden!important}*,*::before,*::after{animation:none!important;transition:none!important;caret-color:transparent!important}',
});
await page.waitForTimeout(500);
const image = await page.screenshot({ fullPage: true, animations: 'disabled' });
await page.close();
return { image, status: response?.status() ?? null };
}

try {
for (const width of viewports) {
for (const [index, route] of routes.entries()) {
const before = await capture(beforeUrl, route, width);
const after = await capture(afterUrl, route, width);
const beforePath = resolve(outputDirectory, `before-${width}-${index}.png`);
const afterPath = resolve(outputDirectory, `after-${width}-${index}.png`);
writeFileSync(beforePath, before.image);
writeFileSync(afterPath, after.image);

const a = await sharp(before.image).raw().toBuffer({ resolveWithObject: true });
const b = await sharp(after.image).raw().toBuffer({ resolveWithObject: true });
const matches = a.info.width === b.info.width
&& a.info.height === b.info.height
&& a.data.equals(b.data)
&& before.status === 200
&& after.status === 200;

if (!matches) failures.push({ width, route, beforeStatus: before.status, afterStatus: after.status });
console.log(`${width}px ${route}: ${matches ? 'MATCH' : 'DIFF'}`);
}
}
} finally {
await browser.close();
}

console.log(`Compared ${routes.length * viewports.length} pages; ${failures.length} mismatches.`);
if (failures.length) {
console.error(JSON.stringify(failures, null, 2));
process.exitCode = 1;
}
5 changes: 0 additions & 5 deletions src/app.html
Original file line number Diff line number Diff line change
Expand Up @@ -44,11 +44,6 @@
</script>
<!-- End Twitter conversion tracking base code -->

<!-- live chat -->
<!--
<script src="//code.tidio.co/9o9hpvuj5fqc7gu1vhialdrpp7buweu2.js" async></script>
-->

<title>comma.ai — make driving chill</title>

<!-- Google SEO -->
Expand Down
1 change: 0 additions & 1 deletion src/lib/components/HomeHeroOverlay.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -111,7 +111,6 @@
<span>try risk-free for 30 days</span>
<span class="action-detail">
<!-- TODO: Show after we have $0 down. -->
<!-- <span>$0 due today</span> -->
<span class="action-arrow" aria-hidden="true">{@html ArrowRight}</span>
</span>
</a>
Expand Down
21 changes: 12 additions & 9 deletions src/lib/components/Product.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
export let disableBuyButtonText = null;
export let hideOutOfStockVariants = false;
export let hideVariantImage = false;
export let hideDefaultShippingNote = false;
export let scrollProductImages = false;
export let inlineMobileTitlePrice = false;
export let previousPrice = null;
Expand Down Expand Up @@ -191,15 +192,17 @@
>
{addToCartLabel}
</Button>
<slot name="shipping">
<NoteCard title="Shipping" icon={ShippingIcon}>
{#if product?.freeRush}
Free Rush (UPS 2nd Day Air) shipping. $30 flat rate internationally.
{:else}
Free US shipping, $30 flat rate internationally.
{/if}
</NoteCard>
</slot>
{#if !hideDefaultShippingNote}
<slot name="shipping">
<NoteCard title="Shipping" icon={ShippingIcon}>
{#if product?.freeRush}
Free Rush (UPS 2nd Day Air) shipping. $30 flat rate internationally.
{:else}
Free US shipping, $30 flat rate internationally.
{/if}
</NoteCard>
</slot>
{/if}
<slot name="notes"></slot>
<hr />
<div class="description">
Expand Down
3 changes: 1 addition & 2 deletions src/lib/components/ProductDescriptions/CommaFour.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -154,8 +154,7 @@

<Product {product} {additionalProductIds} {backordered} {beforeAddToCart} {getCartNote} priceOverride={FOUR_PRICE}
previousPrice={FOUR_STRIKETHROUGH_PRICE} sale={FOUR_SALE}
disableBuyButtonText={disableBuyButtonText}>
<div slot="shipping"></div>
disableBuyButtonText={disableBuyButtonText} hideDefaultShippingNote={true}>

<div slot="price" class="price" class:sale-price={FOUR_SALE}>
{#if referralCode}
Expand Down
4 changes: 1 addition & 3 deletions src/lib/components/SetupStep.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,7 @@
<div class="step-content">
{#if images.length > 0}
<div class="step-images-grid" class:single-image={images.length === 1}>
{#if images.length > 0}
<img src={images[0]} alt={header || `Step ${stepNumber}`} class="step-image step-image-first" />
{/if}
<img src={images[0]} alt={header || `Step ${stepNumber}`} class="step-image step-image-first" />
{#each images.slice(1) as img}
<img src={img} alt={header || `Step ${stepNumber}`} class="step-image" />
{/each}
Expand Down
4 changes: 0 additions & 4 deletions static/neurips.html
Original file line number Diff line number Diff line change
Expand Up @@ -169,14 +169,12 @@ <h2>5 Research rump talks</h2>
- tinygrad: the fastest growing neural network framework [4].<br>
</p>
<figure class="nips-figure">
<!-- Replace with your own image -->
<img src="images/neurips/revH.68.png" alt="Example figure">
<figcaption>
Figure&nbsp;2: comma four exploded view.
</figcaption>
</figure>
<figure class="nips-figure">
<!-- Replace with your own image -->
<img src="images/neurips/tinygrad_stack_plot.png" alt="Example figure">
<figcaption>
Figure&nbsp;3: stack plot of tinygrad lines of code over the years.
Expand All @@ -185,7 +183,6 @@ <h2>5 Research rump talks</h2>

</div>
</div>
<div>
<figure class="nips-figure nips-figure-wide">
<video class="nips-video-wide" controls muted playsinline>
<source src="videos/neurips/captioned_compressed_mlsim.mp4" type="video/mp4">
Expand All @@ -196,7 +193,6 @@ <h2>5 Research rump talks</h2>
Captioned by comma.ai engineers.
</figcaption>
</figure>
</div>
<!-- References -->
<section class="references">
<h2>References</h2>
Expand Down
Loading