import { practice } from "./data/practice.ts"; import { projects, websites } from "./data/projects.ts"; import { tools } from "./data/tools.ts"; import { work } from "./data/work.ts"; const width = 86; const esc = "\x1b"; const color = { reset: `${esc}[0m`, bold: `${esc}[1m`, purple: `${esc}[38;5;141m`, blue: `${esc}[38;5;117m`, amber: `${esc}[38;5;215m`, green: `${esc}[38;5;114m`, text: `${esc}[38;5;252m`, muted: `${esc}[38;5;245m`, border: `${esc}[38;5;240m`, }; type DisplayLine = string | { text: string; style?: string }; function hyperlink(label: string, url: string): string { return `${esc}]8;;${url}${esc}\\${color.blue}${esc}[4m${label}${esc}[24m${esc}]8;;${esc}\\`; } function quietHyperlink(label: string, url: string): string { return `${esc}]8;;${url}${esc}\\${label}${esc}]8;;${esc}\\`; } function decorateLinks(text: string): string { return text.replace( /https?:\/\/[^\s]+|[\w.+-]+@[\w.-]+\.[A-Za-z]{2,}/g, (value) => hyperlink(value, value.includes("@") ? `mailto:${value}` : value), ); } function wrap(text: string, lineWidth = width): string[] { const words = text.split(/\s+/); const lines: string[] = []; let line = ""; for (const word of words) { if (`${line} ${word}`.trim().length > lineWidth) { lines.push(line); line = word; } else { line = `${line} ${word}`.trim(); } } if (line) lines.push(line); return lines; } function section(title: string, lines: DisplayLine[]): string { const label = ` ${title} `; const top = `┌─${label}${"─".repeat(width - label.length - 1)}┐`; const body = lines .flatMap((entry) => { const line = typeof entry === "string" ? entry : entry.text; const style = typeof entry === "string" ? color.text : entry.style; return (line ? wrap(line, width - 4) : [""]).map((text) => ({ text, style, })); }) .map(({ text, style }) => { const content = decorateLinks(text.padEnd(width - 2)); return `${color.border}│${color.reset} ${style ?? ""}${content}${color.reset} ${color.border}│${color.reset}`; }) .join("\n"); const styledTop = top.replace(label, `${color.bold}${color.purple}${label}${color.reset}${color.border}`); return `${color.border}${styledTop}${color.reset}\n${body}\n${color.border}└${"─".repeat(width)}┘${color.reset}`; } const experience = work.flatMap((role, index) => [ { text: role.title.toUpperCase(), style: `${color.bold}${color.purple}` }, { text: `${role.company} · ${role.years}`, style: color.amber }, { text: role.description, style: color.text }, ...(index < work.length - 1 ? [""] : []), ]); const projectList = [...projects, ...websites].flatMap((project, index, all) => [ { text: project.name.toUpperCase(), style: `${color.bold}${color.purple}` }, { text: `${project.type} · ${project.url}`, style: color.amber }, { text: project.description, style: color.text }, ...(index < all.length - 1 ? [""] : []), ]); const competencies = practice.flatMap((area, index) => [ { text: area.title.toUpperCase(), style: `${color.bold}${color.purple}` }, { text: area.body, style: color.text }, ...(index < practice.length - 1 ? [""] : []), ]); const proficiencyOrder = [ "Advanced", "Proficient", "Working knowledge", "Familiar", ] as const; const skills = proficiencyOrder.flatMap((level, index) => { const names = tools .filter((tool) => tool.proficiency === level) .map((tool) => tool.name) .join(" · "); return [ { text: level.toUpperCase(), style: `${color.bold}${color.purple}` }, { text: names, style: color.text }, ...(index < proficiencyOrder.length - 1 ? [""] : []), ]; }); const page = ` ${color.purple} ▄████▄ ▄▄▄▄▄▄▄▄ ▄██▀▀██▄ ███▀▀▀███ ${color.bold}${color.text}OWEN RUMMAGE${color.reset} ${color.purple} ███ ███ ███▄▄▄██▀ ${color.amber}Systems engineer${color.reset} ${color.purple} ▀██▄▄██▀ ███ ▀██▄ ${color.muted}Nashville, Tennessee${color.reset} ${color.purple} ▀████▀ ███ ███ ${color.border} ──────────────────────── ${color.green}Linux · networks · cloud · automation${color.reset} ${color.text} Systems engineer specializing in Linux infrastructure, network engineering, cloud platforms, and automation. Based in Nashville, Tennessee.${color.reset} ${hyperlink("hello@rummage.cc", "mailto:hello@rummage.cc")} ${hyperlink("github.com/owenrummage", "https://github.com/owenrummage")} ${hyperlink("linkedin.com/in/orummage", "https://linkedin.com/in/orummage")} ${hyperlink("rummage.cc", "https://rummage.cc")} ${section("EXPERIENCE", experience)} ${section("EDUCATION", [ { text: "ASSOCIATE OF APPLIED SCIENCE IN COMPUTER INFORMATION TECHNOLOGY", style: `${color.bold}${color.purple}` }, { text: "Nashville State Community College · 2023 - 2026", style: color.amber }, { text: "Concentration in Systems Administration and Management. Graduated May 2026.", style: color.text }, ])} ${section("PROJECTS", projectList)} ${section("CORE COMPETENCIES", competencies)} ${section("TECHNICAL SKILLS", skills)} ${section("APPROACH", [ { text: "I build systems that can be understood and maintained by someone other than me.", style: `${color.bold}${color.green}` }, ])} ${color.muted} $${color.reset} ${color.text}curl rummage.cc${color.reset} ${color.muted}Get this page${color.reset} ${color.muted} $${color.reset} ${color.text}open ${hyperlink("https://rummage.cc", "https://rummage.cc")}${color.reset} ${color.muted}Visit the web version${color.reset} \n${color.muted} Inspired by Dave Eddy's ${quietHyperlink("ysap.sh", "https://ysap.sh")}.${color.reset} ${color.reset}`; export default function () { return new Response(page, { headers: { "Cache-Control": "no-cache, no-store, must-revalidate", "Content-Type": "text/plain; charset=utf-8", Vary: "User-Agent, Accept", "X-Content-Type-Options": "nosniff", }, }); }