Skip to content
Merged
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
7 changes: 6 additions & 1 deletion apps/website/scripts/check-dist.ts
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,9 @@ export function findLiterals(srcFiles: { path: string; text: string }[]): string
);
}

/** Files whose text is code or content; images and fonts are skipped by the literal check. */
export const isSourceText = (path: string) => /\.(astro|ts|tsx|js|mjs|css|md|mdx|json)$/i.test(path);

/** Every rule list that must read the same on the page and in brand.md. */
export function parityRules(b: Brand): string[] {
return [
Expand Down Expand Up @@ -118,7 +121,9 @@ function main(): void {
const brandHtml = read('brand/index.html');
const md = read('brand.md');
const redirects = existsSync(join(dist, '_redirects')) ? parseRedirects(read('_redirects')) : [];
const src = walk(join(app, 'src')).map((p) => ({ path: relative(app, p), text: readFileSync(p, 'utf8') }));
const src = walk(join(app, 'src'))
.filter(isSourceText)
.map((p) => ({ path: relative(app, p), text: readFileSync(p, 'utf8') }));

const errors = [
...required.filter((f) => !existsSync(join(dist, f))).map((f) => `dist/${f} was not built`),
Expand Down
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
8 changes: 4 additions & 4 deletions apps/website/src/content/organizers.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[
{ "id": "cyrus-hiyas", "name": "Cyrus Hiyas", "role": "Lead", "community": "Angular Cebu", "order": 1 },
{ "id": "dorell-james", "name": "Dorell James", "role": "Lead", "community": "React Cebu", "order": 2 },
{ "id": "harlequin-doyon", "name": "Harlequin Doyon", "role": "Lead", "community": "Vue.js Cebu", "order": 3 },
{ "id": "sieg-balona", "name": "Sieg Balona", "role": "Co-Lead", "community": "React Cebu", "order": 4 }
{"id": "cyrus-hiyas", "name": "Cyrus Hiyas", "role": "Lead", "community": "Angular Cebu", "url": "https://www.sleepnotfound.com/", "photo": "../assets/organizers/cyrus-hiyas.jpg", "order": 1},
{"id": "dorell-james", "name": "Dorell James", "role": "Lead", "community": "React Cebu", "url": "https://www.dorelljames.com", "photo": "../assets/organizers/dorell-james.jpg", "order": 2},
{"id": "harlequin-doyon", "name": "Harlequin Doyon", "role": "Lead", "community": "Vue.js Cebu", "url": "https://harlekoy.dev/", "photo": "../assets/organizers/harlequin-doyon.jpg", "order": 3},
{"id": "sieg-balona", "name": "Sieg Balona", "role": "Co-Lead", "community": "React Cebu", "url": "https://siegb.dev/", "photo": "../assets/organizers/sieg-balona.jpg", "order": 4}
]
19 changes: 12 additions & 7 deletions apps/website/src/content/schemas.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,13 +14,18 @@ export const projectSchema = ({ image }: Pick<SchemaContext, 'image'>) =>
order: z.number(),
});

export const organizerSchema = z.object({
id: z.string(),
name: z.string(),
role: z.string(),
community: z.string().optional(),
order: z.number(),
});
export const organizerSchema = ({ image }: Pick<SchemaContext, 'image'>) =>
z.object({
id: z.string(),
name: z.string(),
role: z.string(),
community: z.string().optional(),
/** Their own site. */
url: z.string().url().optional(),
/** A real photo (or the avatar they publish), square, relative to organizers.json. */
photo: image().optional(),
order: z.number(),
});

export const linkSchema = z.object({
id: z.string(),
Expand Down
34 changes: 27 additions & 7 deletions apps/website/src/pages/about.astro
Original file line number Diff line number Diff line change
Expand Up @@ -23,10 +23,13 @@ const organizers = (await getCollection('organizers')).sort((a, b) => a.data.ord
{
organizers.map(({ data }, i) => (
<li data-reveal style={`--i: ${i}`}>
<span class="name">{data.name}</span>
<span class="jc-mono role">
{data.role}
{data.community && ` · ${data.community}`}
{data.photo && <img class="jc-photo face" src={data.photo.src} width="64" height="64" alt="" loading="lazy" />}
<span class="who">
{data.url ? <a class="name" href={data.url}>{`${data.name}\u00a0↗`}</a> : <span class="name">{data.name}</span>}
<span class="jc-mono role">
{data.role}
{data.community && ` · ${data.community}`}
</span>
</span>
</li>
))
Expand Down Expand Up @@ -82,15 +85,32 @@ const organizers = (await getCollection('organizers')).sort((a, b) => a.data.ord
list-style: none;
}
.organizers li {
display: grid;
gap: 4px;
padding: 18px;
display: flex;
align-items: center;
gap: 14px;
padding: 16px;
border: 1px solid var(--jc-line);
border-radius: 10px;
}
.face {
flex: none;
width: 64px;
height: 64px;
border-radius: 50%;
}
.who {
display: grid;
gap: 4px;
min-width: 0;
}
.name {
font-size: 18px;
font-weight: 700;
color: var(--jc-text);
text-decoration: none;
}
a.name:hover {
color: var(--jc-accent);
}
.role {
font-size: 13px;
Expand Down
9 changes: 8 additions & 1 deletion apps/website/test/check-dist.test.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { describe, expect, it } from 'vitest';
import { brand } from '@jscebu/brand';
import { findCursorViolations, findLiterals, findMissingLinks, findParityGaps, parityRules } from '../scripts/check-dist.ts';
import { findCursorViolations, findLiterals, findMissingLinks, findParityGaps, isSourceText, parityRules } from '../scripts/check-dist.ts';

const cursor = '<span class="jc-cursor" aria-hidden="true"></span>';

Expand Down Expand Up @@ -76,3 +76,10 @@ describe('parityRules', () => {
expect(rules).toHaveLength(expected.length);
});
});

describe('isSourceText', () => {
it('scans source files for literals but not images', () => {
expect(['a.astro', 'b.ts', 'c.css', 'd.mjs', 'e.md', 'f.json'].map(isSourceText)).toEqual([true, true, true, true, true, true]);
expect(['g.jpg', 'h.png', 'i.webp', 'j.svg', 'k.woff2'].map(isSourceText)).toEqual([false, false, false, false, false]);
});
});
19 changes: 17 additions & 2 deletions apps/website/test/content.test.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { readFileSync } from 'node:fs';
import { existsSync, readFileSync } from 'node:fs';
import { z } from 'astro/zod';
import { parse } from 'yaml';
import { describe, expect, it } from 'vitest';
Expand All @@ -10,7 +10,7 @@ const frontmatter = (md: string) => parse(md.match(/^---\n([\s\S]*?)\n---/)![1])

describe('site content', () => {
it('lists the four organizers from /members, in order', () => {
const organizers = z.array(organizerSchema).parse(JSON.parse(read('organizers.json')));
const organizers = z.array(organizerSchema({ image: () => z.string() })).parse(JSON.parse(read('organizers.json')));
expect(organizers.map((o) => [o.name, o.role])).toEqual([
['Cyrus Hiyas', 'Lead'],
['Dorell James', 'Lead'],
Expand All @@ -19,6 +19,21 @@ describe('site content', () => {
]);
});

it('links each organizer to their own site', () => {
const organizers = z.array(organizerSchema({ image: () => z.string() })).parse(JSON.parse(read('organizers.json')));
expect(Object.fromEntries(organizers.map((o) => [o.name, o.url]))).toEqual({
'Cyrus Hiyas': 'https://www.sleepnotfound.com/',
'Dorell James': 'https://www.dorelljames.com',
'Harlequin Doyon': 'https://harlekoy.dev/',
'Sieg Balona': 'https://siegb.dev/',
});
});

it('gives each organizer a photo that exists in the repo', () => {
const organizers = z.array(organizerSchema({ image: () => z.string() })).parse(JSON.parse(read('organizers.json')));
for (const o of organizers) expect(existsSync(new URL(o.photo!, new URL('organizers.json', content))), o.name).toBe(true);
});

it('lists the official channels from /official-links', () => {
const links = z.array(linkSchema).parse(JSON.parse(read('links.json')));
expect(links.map((l) => l.url)).toEqual(
Expand Down
Loading