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
8 changes: 7 additions & 1 deletion sites/svelte.dev/src/lib/db/client.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,14 @@ import { dev } from '$app/environment';
import { SUPABASE_URL, SUPABASE_KEY } from '$env/static/private';
import { createClient } from '@supabase/supabase-js';

const client_enabled = !!(!dev || (SUPABASE_URL && SUPABASE_KEY));

/**
* @type {import('@supabase/supabase-js').SupabaseClient<any, "public", any>}
*/
// @ts-ignore-line
export const client =
(!dev || (SUPABASE_URL && SUPABASE_KEY)) &&
client_enabled &&
createClient(SUPABASE_URL, SUPABASE_KEY, {
global: { fetch },
auth: { persistSession: false }
Expand Down
12 changes: 9 additions & 3 deletions sites/svelte.dev/src/lib/db/gist.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,10 @@ const PAGE_SIZE = 90;

/**
* @param {User} user
* @param {{
* offset: number;
* search: string | null;
* }} opts
*/
export async function list(user, { offset, search }) {
const { data, error } = await client.rpc('gist_list', {
Expand All @@ -20,9 +24,11 @@ export async function list(user, { offset, search }) {
if (error) throw new Error(error.message);

// normalize IDs
data.forEach((gist) => {
gist.id = gist.id.replace(/-/g, '');
});
data.forEach(
/** @param {{id:string}} gist */ (gist) => {
gist.id = gist.id.replace(/-/g, '');
}
);

return {
gists: data.slice(0, PAGE_SIZE),
Expand Down
6 changes: 3 additions & 3 deletions sites/svelte.dev/src/lib/db/session.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import { client } from './client.js';
/** @typedef {import('./types').User} User */

/**
* @type {import('flru').flruCache<User>}
* @type {import('flru').flruCache<User | null>}
*/
const session_cache = flru(1000);

Expand Down Expand Up @@ -39,7 +39,7 @@ export async function create(user) {

/**
* @param {string} sessionid
* @returns {Promise<User>}
* @returns {Promise<User | null>}
*/
export async function read(sessionid) {
if (!sessionid) return null;
Expand All @@ -58,7 +58,7 @@ export async function read(sessionid) {
);
}

return session_cache.get(sessionid);
return session_cache.get(sessionid) || null;
}

/** @param {string} sessionid */
Expand Down
12 changes: 9 additions & 3 deletions sites/svelte.dev/src/lib/server/docs/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,7 @@ export function get_docs_list(docs_data) {
}));
}

/** @param {string} str */
const titled = async (str) =>
removeMarkdown(
escape(await markedTransform(str, { paragraph: (txt) => txt }))
Expand All @@ -111,7 +112,10 @@ const titled = async (str) =>
.replace(/<(\/)?(em|b|strong|code)>/g, '')
);

/** @param {string} markdown */
/**
* @param {string} markdown
* @returns {Promise<import('./types').Section[]>}
*/
export async function get_sections(markdown) {
const lines = markdown.split('\n');
const root = /** @type {import('./types').Section} */ ({
Expand Down Expand Up @@ -141,7 +145,9 @@ export async function get_sections(markdown) {
};

// Add the new node to the tree
currentNodes[level].sections.push(newNode);
const sections = currentNodes[level].sections;
if (!sections) throw new Error(`Could not find section ${level}`);
sections.push(newNode);

// Prepare for potential children of the new node
currentNodes = currentNodes.slice(0, level + 1);
Expand All @@ -152,5 +158,5 @@ export async function get_sections(markdown) {
}
}

return root.sections;
return /** @type {import('./types').Section[]} */ (root.sections);
}
14 changes: 13 additions & 1 deletion sites/svelte.dev/src/lib/server/examples/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ export async function get_examples_data(base = CONTENT_BASE_PATHS.EXAMPLES) {
const examples = [];

for (const subdir of await readdir(base)) {
/** @type {import('./types').ExamplesDatum} */
const section = {
title: '', // Initialise with empty
slug: subdir.split('-').slice(1).join('-'),
Expand All @@ -51,13 +52,24 @@ export async function get_examples_data(base = CONTENT_BASE_PATHS.EXAMPLES) {
await readFile(`${example_base_dir}/meta.json`, 'utf-8')
).title;

/**
* @type {Array<{
* name: string;
* type: string;
* content: string;
* }>}
*/
const files = [];
for (const file of (await readdir(example_base_dir)).filter(
(file) => !file.endsWith('meta.json')
)) {
const type = file.split('.').at(-1);
if (!type) {
throw new Error(`Could not determine type from ${file}`);
}
files.push({
name: file,
type: file.split('.').at(-1),
type,
content: await readFile(`${example_base_dir}/${file}`, 'utf-8')
});
}
Expand Down
6 changes: 4 additions & 2 deletions sites/svelte.dev/src/lib/server/examples/types.d.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
export type ExamplesData = {
export interface ExamplesDatum {
title: string;
slug: string;
examples: {
Expand All @@ -10,7 +10,9 @@ export type ExamplesData = {
name: string;
}[];
}[];
}[];
}

export type ExamplesData = ExamplesDatum[];

export interface Example {
title: string;
Expand Down
13 changes: 12 additions & 1 deletion sites/svelte.dev/src/lib/server/tutorial/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ export async function get_tutorial_data(base = CONTENT_BASE_PATHS.TUTORIAL) {
const tutorials = [];

for (const subdir of await readdir(base)) {
/** @type {import('./types').TutorialDatum} */
const section = {
title: '', // Initialise with empty
slug: subdir.split('-').slice(1).join('-'),
Expand All @@ -55,6 +56,12 @@ export async function get_tutorial_data(base = CONTENT_BASE_PATHS.TUTORIAL) {
const { metadata, body } = extractFrontmatter(contents);

// Get the contents of the apps.
/**
* @type {{
* initial: import('./types').CompletionState[];
* complete: import('./types').CompletionState[];
* }}
*/
const completion_states_data = { initial: [], complete: [] };
for (const app_dir of await readdir(tutorial_base_dir)) {
if (!app_dir.startsWith('app-')) continue;
Expand All @@ -63,9 +70,13 @@ export async function get_tutorial_data(base = CONTENT_BASE_PATHS.TUTORIAL) {
const app_contents = await readdir(app_dir_path, 'utf-8');

for (const file of app_contents) {
const type = file.split('.').at(-1);
if (!type) {
throw new Error(`Could not determine type from ${file}`);
}
completion_states_data[app_dir === 'app-a' ? 'initial' : 'complete'].push({
name: file,
type: file.split('.').at(-1),
type,
content: await readFile(`${app_dir_path}/${file}`, 'utf-8')
});
}
Expand Down
16 changes: 12 additions & 4 deletions sites/svelte.dev/src/lib/server/tutorial/types.d.ts
Original file line number Diff line number Diff line change
@@ -1,15 +1,23 @@
export type TutorialData = {
export interface TutorialDatum {
title: string;
slug: string;
tutorials: {
title: string;
slug: string;
dir: string;
content: string;
initial: { name: string; type: string; content: string }[];
complete: { name: string; type: string; content: string }[];
initial: CompletionState[];
complete: CompletionState[];
}[];
}[];
}

export interface CompletionState {
name: string;
type: string;
content: string;
}

export type TutorialData = TutorialDatum[];

export interface Tutorial {
title: string;
Expand Down
50 changes: 24 additions & 26 deletions sites/svelte.dev/src/lib/time.js
Original file line number Diff line number Diff line change
@@ -1,30 +1,28 @@
// adapted from https://github.com/digplan/time-ago
// https://github.com/digplan/time-ago/blob/master/license.txt
const o = {
second: 1000,
minute: 60 * 1000,
hour: 60 * 1000 * 60,
day: 24 * 60 * 1000 * 60,
week: 7 * 24 * 60 * 1000 * 60,
month: 30 * 24 * 60 * 1000 * 60,
year: 365 * 24 * 60 * 1000 * 60
const formatter = new Intl.RelativeTimeFormat(undefined, {
numeric: 'auto'
});

const DIVISIONS = {
seconds: 60,
minutes: 60,
hours: 24,
days: 7,
weeks: 4.34524,
months: 12,
years: Number.POSITIVE_INFINITY
};

export const ago = (nd, s) => {
var r = Math.round,
dir = ' ago',
pl = function (v, n) {
return s === undefined ? n + ' ' + v + (n > 1 ? 's' : '') + dir : n + v.substring(0, 1);
},
ts = Date.now() - new Date(nd).getTime(),
ii;
if (ts < 0) {
ts *= -1;
dir = ' from now';
}
for (var i in o) {
if (r(ts) < o[i]) return pl(ii || 'm', r(ts / (o[ii] || 1)));
ii = i;
/**
* @param {Date} date
*/
export const ago = (date) => {
let duration = (date.getTime() - new Date().getTime()) / 1000;

for (const [name, amount] of Object.entries(DIVISIONS)) {
if (Math.abs(duration) < amount) {
const format = /** @type {keyof(DIVISIONS)} */ (name);
return formatter.format(Math.round(duration), format);
}
duration /= amount;
}
return pl(i, r(ts / o[i]));
};
6 changes: 6 additions & 0 deletions sites/svelte.dev/src/lib/utils/events.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,13 @@
/** @param {number} code */
export function keyEvent(code) {
/**
* @param {HTMLInputElement} node
* @param {(event: KeyboardEvent) => void} callback
*/
return function (node, callback) {
node.addEventListener('keydown', handleKeydown);

/** @param {KeyboardEvent} event */
function handleKeydown(event) {
if (event.keyCode === code) {
callback.call(this, event);
Expand Down
10 changes: 10 additions & 0 deletions sites/svelte.dev/src/lib/utils/examples.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,11 @@
/**
* @param {Array<{
* content: string;
* name: string;
* source: string;
* type: string;
* }>} files
*/
export function process_example(files) {
return files
.map((file) => {
Expand All @@ -12,5 +20,7 @@ export function process_example(files) {

if (a.type === 'svelte') return -1;
if (b.type === 'svelte') return 1;

return 0;
});
}
3 changes: 2 additions & 1 deletion sites/svelte.dev/src/routes/(authed)/apps/+page.server.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,8 @@ export async function load({ url, parent }) {
const { user } = await parent();

if (user) {
const offset = url.searchParams.get('offset') ? parseInt(url.searchParams.get('offset')) : 0;
const offset_param = url.searchParams.get('offset');
const offset = offset_param ? parseInt(offset_param) : 0;
const search = url.searchParams.get('search');

({ gists, next } = await gist.list(user, { offset, search }));
Expand Down
11 changes: 4 additions & 7 deletions sites/svelte.dev/src/routes/(authed)/repl/+page.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,17 +8,14 @@ export function load({ url }) {
const vim = query.get('vim');

// redirect to v2 REPL if appropriate
if (/^[^>]?[12]/.test(version)) {
if (version && /^[^>]?[12]/.test(version)) {
throw redirect(302, `https://v2.svelte.dev/repl?${query}`);
}

const id = gist || example || 'hello-world';
// we need to filter out null values
const q = new URLSearchParams(
Object.entries({
version,
vim
}).filter(([, value]) => value !== null)
).toString();
const q = new URLSearchParams();
if (version) q.set('version', version);
if (vim) q.set('vim', vim);
throw redirect(301, `/repl/${id}?${q}`);
}
Original file line number Diff line number Diff line change
Expand Up @@ -189,7 +189,7 @@ export default app;`
<svelte:window on:keydown={handleKeydown} />

<div class="app-controls">
<input bind:value={name} on:focus={(e) => e.target.select()} use:enter={(e) => e.target.blur()} />
<input bind:value={name} on:focus={(e) => e.target.select()} use:enter={(e) => /** @type {HTMLInputElement} */ (e.target).blur()} />

<div class="buttons">
<button class="icon" on:click={() => (zen_mode = !zen_mode)} title="fullscreen editor">
Expand Down
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
/**
* @param {Blob} blob
* @param {string} filename
*/
export default (blob, filename) => {
const url = URL.createObjectURL(blob);
const link = document.createElement('a');
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -46,9 +46,8 @@ export async function GET({ params }) {
.map((example) => example.slug)
);

if (examples.has(params.id)) {
const example = get_example(examples_data, params.id);

const example = get_example(examples_data, params.id);
if (example) {
return json({
id: params.id,
name: example.title,
Expand Down
15 changes: 7 additions & 8 deletions sites/svelte.dev/src/routes/auth/callback/+server.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,13 @@ import { oauth, client_id, client_secret } from '../_config.js';
export async function GET({ url }) {
try {
// Trade "code" for "access_token"
const r1 = await fetch(
`${oauth}/access_token?` +
new URLSearchParams({
code: url.searchParams.get('code'),
client_id,
client_secret
}).toString()
);
const code = url.searchParams.get('code') || undefined;
const params = new URLSearchParams({
client_id,
client_secret
});
if (code) params.set('code', code);
const r1 = await fetch(`${oauth}/access_token?` + params.toString());
const access_token = new URLSearchParams(await r1.text()).get('access_token');

// Now fetch User details
Expand Down
Loading