33} as const;
34
35export function validateRequired(params: any, required: string[]): void {
36 for (const field of required) {
37 if (params[field] === undefined || params[field] === null) {
44}
45
46export function sanitizeKey(key: string): string {
47 // Ensure blob keys are safe
48 return key.replace(/[^a-zA-Z0-9_\-\.\/]/g, '_');
33- [x] fix wonky sidebar separator height problem (thanks to @stevekrouse)
34- [x] make result tables scrollable
35- [x] add export to CSV, and JSON (CSV and JSON helper functions written in [this val](https://www.val.town/v/nbbaier/sqliteExportHelpers). Thanks to @pomdtr for merging the initial version!)
36- [x] add listener for cmd+enter to submit query
37
11}
12
13async function fetchRandomWikipediaArticle(): Promise<{ title: string; extract: string; pageId: number } | null> {
14 try {
15 const response = await fetch('https://en.wikipedia.org/w/api.php?action=query&format=json&prop=extracts&meta=&generator=random&formatversion=2&exsentences=1&explaintext=1&grnnamespace=0');
37}
38
39export default async function(req: Request): Promise<Response> {
40 const article = await fetchRandomWikipediaArticle();
41
11- **World Icon**: Clean SVG world icon that links to the full Wikipedia article
12- **Responsive**: Works well on desktop and mobile devices
13- **Error Handling**: Graceful error handling with retry functionality
14- **Fast Loading**: No client-side API calls means instant content display
15
39- **No JavaScript**: Completely static HTML with CSS-only animations
40- **Wikipedia API Integration**: Fetches random articles using the Wikipedia API on the server
41- **Error Handling**: Proper error states with retry functionality
42- **Clean Architecture**: Separation of data fetching and HTML generation
43- **Performance**: Fast loading since no client-side API calls are needed
4let linkClass = "text-sky-600 hover:text-sky-500";
5
6export default function FAQ(c) {
7 const userEmail = c.req.header("X-LastLogin-Email");
8
4import Layout from "./layout";
5
6function absoluteURL(url) {
7 if (url.startsWith("http://") || url.startsWith("https://"))
8 return url;
24let linkClass = "text-sky-600 hover:text-sky-500";
25
26function httpsIfy(url: string) {
27 if (!url.startsWith("http://") && !url.startsWith("https://")) {
28 return `https://${url}`;
31}
32
33function renderCell(header, row) {
34 let data = row[header];
35 if (header === "Name") {
45}
46
47export default async function Browse(c) {
48 const userEmail = c.req.header("X-LastLogin-Email");
49 const url = new URL(c.req.url);
3import Layout from "./layout";
4
5export default function Home(c) {
6 const userEmail = c.req.header("X-LastLogin-Email");
7
45
46// Get existing profile for a user
47async function getUserProfile(userEmail: string) {
48 try {
49 const { columns, rows } = await sqlite.execute({
384};
385// Database migration to add UserEmail column if it doesn't exist
386async function ensureUserEmailColumn() {
387 try {
388 // Try to add the UserEmail column - this will fail if it already exists, which is fine
6const thisURL = parseProject(import.meta.url).links.self.project;
7
8export default function({ activeTab, children, userEmail }: PropsWithChildren<{ activeTab: string; userEmail?: string }>) {
9 return (
10 <html>
3import { zip } from "npm:lodash-es";
4
5export async function rss(req: Request) {
6 let { columns, rows } = await sqlite.execute(`select * from datemedocs order by LastUpdated desc limit 20`);
7 const profiles = rows.map(row =>
A helper function to build a file's email
Simple functional CSS library for Val Town
import { OpenAI } from "https://esm.town/v/std/openai";
export default async function(req: Request): Promise<Response> {
if (req.method === "OPTIONS") {
return new Response(null, {
headers: {
"Access-Control-Allow-Origin": "*",
LangChain (https://langchain.com) Ambassador, KubeSphere (https://kubesphere.io) Ambassador, CNCF OpenFunction (https://openfunction.dev) TOC Member.