blob_adminREADME.md1 match
46- Collapsible/expandable object and array nodes
47- Syntax highlighting
48- Copy functionality
49- Edit mode with JSON validation
50- Error handling for invalid JSON
blob_adminutils.ts3 matches
45];
4647export function isImage(path: string) {
48return COMMON_IMAGE_EXTENSIONS.includes(path.split(".").pop());
49}
5051export function isText(path: string) {
52return COMMON_TEXT_EXTENSIONS.includes(path.split(".").pop());
53}
5455export function isJSON(path: string, text?: string, size?: number): boolean {
56// Check if file extension is .json
57if (path.endsWith('.json')) {
2import { Layout } from "./Layout.tsx";
34export function NotAuthorizedPage(
5{ username, email }: { username: string; email: string },
6) {
blob_adminNewPage.tsx1 match
2import { Layout } from "./Layout.tsx";
34export function NewPage(props) {
5return (
6<Layout>
blob_adminLoginPage.tsx1 match
2import { Layout } from "./Layout.tsx";
34export function LoginPage({ username }: { username: string }) {
5return (
6<Layout showLogout={false}>
blob_adminLayout.tsx1 match
1/** @jsxImportSource npm:hono/jsx */
23export function Layout({ children, showLogout = true }) {
4return (
5<html>
blob_adminBlobPage.tsx1 match
5type Blob = Awaited<ReturnType<typeof blob.list>>[number];
67export function BlobPage({ name, error, type, text, metadata }: {
8name: string;
9metadata?: Blob;
1export default async function(req: Request): Promise<Response> {
2const html = `<!DOCTYPE html>
3<html lang="en">
212<script>
213// Cookie utilities
214function setCookie(name, value, days = 30) {
215const expires = new Date();
216expires.setTime(expires.getTime() + (days * 24 * 60 * 60 * 1000));
218}
219220function getCookie(name) {
221const nameEQ = name + "=";
222const ca = document.cookie.split(';');
230231// Load saved values
232function loadSavedValues() {
233// Load API key from cookie
234const savedApiKey = getCookie('nvidia_api_key');
261262// Save current form values
263function saveCurrentValues() {
264const form = document.getElementById('apiForm');
265const formData = new FormData(form);
298299// Make API request
300async function makeApiRequest(requestData, apiKey) {
301const response = await fetch('https://integrate.api.nvidia.com/v1/chat/completions', {
302method: 'POST',
313314// Handle streaming response
315async function handleStreamingResponse(response) {
316const reader = response.body.getReader();
317const decoder = new TextDecoder();
352353// Handle non-streaming response
354async function handleNonStreamingResponse(response) {
355const responseDiv = document.getElementById('responseContent');
356
untitled-7971main.ts1 match
2const BASE_URL = "https://api.longcat.chat/openai";
34export default async function (req: Request): Promise<Response> {
5const data = {
6"model": "LongCat-Flash-Chat",
96type SectionId = keyof typeof AD_SECTION_TITLES;
9798function textClean(s?: string | null): string {
99return (s ?? "")
100.replace(/\u00AD/g, "") // soft hyphen
103}
104105// function getProvider(doc: Document): AerodromeAD2["meta"]["provider"] {
106// const host = textClean(doc.querySelector("base")?.href || "");
107// const html = doc.documentElement.outerHTML;
112// return "OTHER";
113// }
114function getProvider(
115doc: Document,
116sourceUrl?: string,
127128// Find all headings that look like “AD 2.x …”
129function findAllAdHeadings(doc: Document): HTMLElement[] {
130const candidates = Array.from(doc.querySelectorAll("h1,h2,h3,h4,h5"));
131return candidates.filter((h) => /AD[\s\h]*2\.\d+/.test(h.textContent || ""));
133134// // Get the content nodes that belong to one AD 2.x heading, up to next AD 2.* heading
135// function collectSectionContent(start: HTMLElement): HTMLElement[] {
136// const content: HTMLElement[] = [];
137// let el = start.nextElementSibling as HTMLElement | null;
147// }
148149function findSectionsInOnePass(doc: Document): AdSection[] {
150const sections: AdSection[] = [];
151const headingRegex = /^(?:[A-Z]{4}[\s\h]+)?AD[\s\h]*2\.(\d+)\b/i;
180}
181182function collectSectionContent(
183start: HTMLElement,
184allHeadings: HTMLElement[],
194195// Extract first table inside nodes; optionally all tables
196function findTables(nodes: HTMLElement[]): HTMLTableElement[] {
197return nodes.flatMap((n) => Array.from(n.querySelectorAll("table")));
198}
199200// Convert a table to a matrix of strings
201function tableToMatrix(table: HTMLTableElement): string[][] {
202const rows = Array.from(table.querySelectorAll("tr"));
203return rows.map((tr) =>
209210// Generic: pick best header row (heuristic)
211function detectHeaderRow(
212matrix: string[][],
213): { header: string[]; body: string[][] } {
227228// Map body rows to objects by header
229function matrixToObjects(
230header: string[],
231body: string[][],
244245// Key-value tables: try to read “label -> value” across rows
246function parseKeyValueMatrix(matrix: string[][]): Record<string, string> {
247const out: Record<string, string> = {};
248for (const row of matrix) {
264// Section-specific parsers
265266function parseAD21(nodes: HTMLElement[]): AD21_Location | undefined {
267// Often the page title or the first heading includes “EGBE — COVENTRY” etc.
268// Try heading text, else look in AD 2.1 table.
293}
294295function parseAD22(
296nodes: HTMLElement[],
297provider: AerodromeAD2["meta"]["provider"],
341}
342343function parseAD212(
344nodes: HTMLElement[],
345provider: AerodromeAD2["meta"]["provider"],
408}
409410function parseAD218(
411nodes: HTMLElement[],
412provider: AerodromeAD2["meta"]["provider"],
458}
459460function parseAD224(nodes: HTMLElement[]): AD224_Charts | undefined {
461const tables = findTables(nodes);
462if (tables.length === 0) return undefined;
483}
484485export async function parseAIP(
486html: string,
487sourceUrl?: string,