Add ESLint and Prettier
Prettier owns formatting: .prettierrc.json, format and format:check scripts, and a one-off pass over the repo so the check is green from the start. Embedded language formatting is off deliberately - the renderers build HTML in html tagged templates and letting Prettier reflow those would change the markup customers receive. docs/ is excluded because it is hand-wrapped prose, and shell scripts have no Prettier parser. ESLint covers the JavaScript: the two browser scripts, the build and check scripts, and its own config. no-var is scoped out for the browser scripts on purpose; they are plain ES5-shaped IIFEs and a hoisting difference would only show up in a browser. ESLint cannot lint the TypeScript here: typescript@7 is the native port with no JavaScript compiler API, and typescript-eslint requires a 4.8-6.1 peer, so it refuses to install and forcing it through would leave a parser that cannot read the compiler. tsc --noEmit stays the TypeScript gate; README records the two ways to change that. lint and format:check now run in deploy.sh, and VS Code formats on save with Prettier and surfaces ESLint findings.
This commit is contained in:
1 parent
ce8079355b
commit
e64f65642f
40 files changed
+1469
-172
No files matched your search
+44
-9
@@ -3,7 +3,13 @@ import { rm } from 'node:fs/promises';
|
||||
import path from 'node:path';
|
||||
import { afterEach, beforeEach, describe, it } from 'node:test';
|
||||
import type { FastifyInstance } from 'fastify';
|
||||
import { LoginThrottle, SESSION_COOKIE, createSessionToken, csrfToken, hashPassword } from '../src/auth.ts';
|
||||
import {
|
||||
LoginThrottle,
|
||||
SESSION_COOKIE,
|
||||
createSessionToken,
|
||||
csrfToken,
|
||||
hashPassword,
|
||||
} from '../src/auth.ts';
|
||||
import { parseSiteConfig } from '../src/config.ts';
|
||||
import { buildApp } from '../src/server.ts';
|
||||
import { FakePipeline, pngBytes, tempDir, testClock } from './support/harness.ts';
|
||||
@@ -237,7 +243,11 @@ describe('the editor', () => {
|
||||
assert.equal(response.statusCode, 303);
|
||||
assert.equal(response.headers['location'], `/admin/sets/${id}`);
|
||||
|
||||
const editor = await app.inject({ method: 'GET', url: `/admin/sets/${id}`, cookies: cookies() });
|
||||
const editor = await app.inject({
|
||||
method: 'GET',
|
||||
url: `/admin/sets/${id}`,
|
||||
cookies: cookies(),
|
||||
});
|
||||
assert.equal(editor.statusCode, 200);
|
||||
assert.match(editor.body, /data-drop/);
|
||||
assert.match(editor.body, /data-pages-admin/);
|
||||
@@ -281,7 +291,11 @@ describe('uploading Pages', () => {
|
||||
assert.equal(response.statusCode, 200);
|
||||
assert.deepEqual(response.json(), { added: 1, failed: [] });
|
||||
|
||||
const editor = await app.inject({ method: 'GET', url: `/admin/sets/${id}`, cookies: cookies() });
|
||||
const editor = await app.inject({
|
||||
method: 'GET',
|
||||
url: `/admin/sets/${id}`,
|
||||
cookies: cookies(),
|
||||
});
|
||||
assert.match(editor.body, /IMG_0001\.JPG/);
|
||||
assert.match(editor.body, /\/media\/thumb-/);
|
||||
});
|
||||
@@ -566,7 +580,11 @@ describe('forms as a browser sends them', () => {
|
||||
it('publishes from the editor form, with no CSRF header', async () => {
|
||||
const { id } = await newSet();
|
||||
await upload(id, 'one.jpg');
|
||||
const editor = await app.inject({ method: 'GET', url: `/admin/sets/${id}`, cookies: cookies() });
|
||||
const editor = await app.inject({
|
||||
method: 'GET',
|
||||
url: `/admin/sets/${id}`,
|
||||
cookies: cookies(),
|
||||
});
|
||||
const response = await app.inject({
|
||||
method: 'POST',
|
||||
url: `/admin/sets/${id}/publish`,
|
||||
@@ -582,7 +600,11 @@ describe('forms as a browser sends them', () => {
|
||||
await upload(id, 'one.jpg');
|
||||
await upload(id, 'two.jpg');
|
||||
const before = (await app.menu.store.get(id)).manifest.pages.map((page) => page.id);
|
||||
const editor = await app.inject({ method: 'GET', url: `/admin/sets/${id}`, cookies: cookies() });
|
||||
const editor = await app.inject({
|
||||
method: 'GET',
|
||||
url: `/admin/sets/${id}`,
|
||||
cookies: cookies(),
|
||||
});
|
||||
const response = await app.inject({
|
||||
method: 'POST',
|
||||
url: `/admin/sets/${id}/move`,
|
||||
@@ -606,7 +628,11 @@ describe('forms as a browser sends them', () => {
|
||||
|
||||
it('accepts the token as a multipart field, the way the no-JS upload form sends it', async () => {
|
||||
const { id } = await newSet();
|
||||
const editor = await app.inject({ method: 'GET', url: `/admin/sets/${id}`, cookies: cookies() });
|
||||
const editor = await app.inject({
|
||||
method: 'GET',
|
||||
url: `/admin/sets/${id}`,
|
||||
cookies: cookies(),
|
||||
});
|
||||
const token = csrfFrom(editor.body);
|
||||
|
||||
const boundary = '----formboundary';
|
||||
@@ -661,9 +687,14 @@ describe('forms as a browser sends them', () => {
|
||||
const { id } = await newSet('bar', 'Bar Menu');
|
||||
await upload(id, 'one.jpg');
|
||||
const dashboard = (await app.inject({ method: 'GET', url: '/admin', cookies: cookies() })).body;
|
||||
const editor = (await app.inject({ method: 'GET', url: `/admin/sets/${id}`, cookies: cookies() })).body;
|
||||
const editor = (
|
||||
await app.inject({ method: 'GET', url: `/admin/sets/${id}`, cookies: cookies() })
|
||||
).body;
|
||||
|
||||
for (const [where, body] of [['dashboard', dashboard], ['editor', editor]] as const) {
|
||||
for (const [where, body] of [
|
||||
['dashboard', dashboard],
|
||||
['editor', editor],
|
||||
] as const) {
|
||||
const forms = [...body.matchAll(/<form\b[^>]*>[\s\S]*?<\/form>/g)].map((match) => match[0]);
|
||||
assert.ok(forms.length > 0, `no forms found in the ${where}`);
|
||||
for (const form of forms) {
|
||||
@@ -691,7 +722,11 @@ describe('reordering', () => {
|
||||
it('offers dragging on the Current set and the new order reaches customers', async () => {
|
||||
const id = await publishBar('Bar Menu', '2026-06-26');
|
||||
|
||||
const editor = await app.inject({ method: 'GET', url: `/admin/sets/${id}`, cookies: cookies() });
|
||||
const editor = await app.inject({
|
||||
method: 'GET',
|
||||
url: `/admin/sets/${id}`,
|
||||
cookies: cookies(),
|
||||
});
|
||||
assert.equal(editor.statusCode, 200);
|
||||
assert.match(editor.body, /data-pages-admin/);
|
||||
assert.match(editor.body, /page-admin__handle/);
|
||||
|
||||
Reference in new issue
Block a user