mirror of
https://github.com/IliesAllali/parenthese.git
synced 2026-11-06 23:32:08 +00:00
- Règles de préchargement dans l'accueil et les 15 guides : une page du site est préparée quand on survole son lien (appui sur téléphone), et s'ouvre presque tout de suite. Pages seulement, pas les fichiers ; l'application n'est pas concernée. Ignoré par les navigateurs qui ne connaissent pas ces règles. - Une page préchargée ne compte pas de visite avant d'être vraiment ouverte (PostHog attend prerenderingchange), et l'animation du logo se joue à l'ouverture, pas pendant le préchargement. - CSP de la landing (deploy/nginx.conf) : empreinte des règles, et nouvelle empreinte du script du logo. Le mot-clé 'inline-speculation-rules' ne suffisait pas à Chrome. - Test : chaque script en ligne des pages a son empreinte dans la CSP, chaque page a ses règles. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
40 lines
2.0 KiB
JavaScript
40 lines
2.0 KiB
JavaScript
// Les scripts en ligne de la landing (animation du logo, règles de préchargement des pages) ne passent la CSP de
|
|
// nginx que par leur empreinte exacte (deploy/nginx.conf). Un script modifié sans recalculer son empreinte ne
|
|
// casse rien de visible : l'animation ou le préchargement s'arrêtent sans bruit. Ce test le dit tout de suite.
|
|
import { test } from 'node:test'
|
|
import assert from 'node:assert/strict'
|
|
import { createHash } from 'node:crypto'
|
|
import { readFileSync, readdirSync, statSync } from 'node:fs'
|
|
import path from 'node:path'
|
|
import { fileURLToPath } from 'node:url'
|
|
|
|
const landing = fileURLToPath(new URL('..', import.meta.url))
|
|
const csp = readFileSync(path.join(landing, '../deploy/nginx.conf'), 'utf8').match(/map \$host \$parenthese_landing_csp \{\s*default "([^"]+)"/)[1]
|
|
const autorisees = new Set([...csp.matchAll(/'sha256-([^']+)'/g)].map((m) => m[1]))
|
|
const empreinte = (texte) => createHash('sha256').update(texte, 'utf8').digest('base64')
|
|
|
|
function pages(dossier) {
|
|
return readdirSync(dossier).flatMap((nom) => {
|
|
const chemin = path.join(dossier, nom)
|
|
if (statSync(chemin).isDirectory()) return pages(chemin)
|
|
return nom === 'index.html' ? [chemin] : []
|
|
})
|
|
}
|
|
const toutes = [path.join(landing, 'index.html'), ...pages(path.join(landing, 'public'))]
|
|
|
|
test('chaque script en ligne des pages a son empreinte dans la CSP de la landing', () => {
|
|
for (const fichier of toutes) {
|
|
const html = readFileSync(fichier, 'utf8')
|
|
for (const [, attributs, contenu] of html.matchAll(/<script([^>]*)>([\s\S]*?)<\/script>/g)) {
|
|
if (/\bsrc=|application\/ld\+json/.test(attributs)) continue
|
|
assert.ok(autorisees.has(empreinte(contenu)), `${path.relative(landing, fichier)} : script en ligne sans empreinte dans deploy/nginx.conf (${empreinte(contenu)})`)
|
|
}
|
|
}
|
|
})
|
|
|
|
test('chaque page a ses règles de préchargement', () => {
|
|
for (const fichier of toutes) {
|
|
assert.match(readFileSync(fichier, 'utf8'), /<script type="speculationrules">/, path.relative(landing, fichier))
|
|
}
|
|
})
|