heartwood every commit a ring

Add markdown-based resume generation system and update resume content

adb60c7b by Isaac Bythewood · 1 month ago

Add markdown-based resume generation system and update resume content

Add resume generation pipeline using marked, gray-matter, and Playwright
to convert a markdown source file into a styled PDF. Update resume with
current role as Senior Solutions Architect at Craftmaster Furniture,
modernized skills and technologies, and new project highlights. Add
self-unregistering service worker to clear stale browser registrations.
modified Makefile
@@ -1,4 +1,4 @@.PHONY: run push.PHONY: run push resumerun:	yarn start
@@ -6,3 +6,6 @@ run:push:	git push origin	git push serverresume:	yarn resume
modified package.json
@@ -3,11 +3,15 @@  "scripts": {    "start": "next --port 8000",    "next:start": "next start --port ${PORT}",    "next:build": "next build"    "next:build": "next build",    "resume": "node resume/generate.js"  },  "dependencies": {    "@babel/core": "^7.29.0",    "gray-matter": "^4.0.3",    "marked": "^17.0.6",    "next": "^16.2.2",    "playwright": "^1.59.1",    "react": "^19.2.4",    "react-dom": "^19.2.4",    "react-is": "^19.2.4",
modified public/static/pdfs/resume-isaac-bythewood.pdf

binary file

added public/static/sw.js
@@ -0,0 +1,4 @@self.addEventListener("install", () => self.skipWaiting());self.addEventListener("activate", () => {  self.registration.unregister();});
added resume/content.md
@@ -0,0 +1,96 @@---name: Isaac Bythewoodtitle: Senior Solutions Architectsummary: Senior Solutions Architect with two decades of experience building across the full stack, from DevOps and server infrastructure to AI agent workflows, leading teams through demanding delivery schedules in highly regulated environments.location: Jonesville, NC 28642phone: (540) 200-8459email: isaac@bythewood.melinks:  - url: https://isaacbythewood.com    label: isaacbythewood.com  - url: https://linkedin.com/in/ibythewood    label: linkedin.com/in/ibythewood  - url: https://github.com/overshard    label: github.com/overshardskills:  - Solutions Architecture  - Full-Stack Development  - AI Agent Workflows  - DevOps & CI/CD  - Linux Administration  - Container Orchestration  - Data Visualization  - Browser Automation & Testing  - API Design  - Infrastructure as Code  - Web Scraping & Analyticstechnologies:  - Python  - JavaScript  - CSS  - HTML  - Django  - Flask  - Next.js  - React  - PostgreSQL  - Redis  - Docker  - Linux  - Playwright  - Webpack  - Three.js  - Chart.js  - Anthropic SDK  - Pandas  - LangChain  - PyTorch  - Hugging Face Transformerseducation:  - institution: Virginia Tech    years: 2008 - 2012    degree: Computer Science---## Recent Experience### Craftmaster Furniture — *Senior Solutions Architect*Furniture Manufacturer — JULY 2024 - CURRENT- Leading modernization of legacy IBM iSeries infrastructure to a modern Ubuntu, PostgreSQL, and Django stack.- Built an in-house 3D furniture viewer with full fabric draping across 1,000+ fabrics and real-time customization, replacing costly third-party solutions at a fraction of the price.- Rebuilt internal and external portals with AI-driven insights and modernized reporting, reducing time spent by sales and marketing teams on legacy systems.- Redesigned company websites with modern responsive design, improved performance, and reduced attack surface by consolidating platforms and syncing data, saving hundreds of man-hours every market.- Built customer-facing APIs for real-time pricing and catalog data, cutting time to market for new products.### Gryphos Creative — *Head of Web Development*Full-Service Marketing Agency — APRIL 2023 - JULY 2024- Migrated all websites and services to a more secure and cheaper hosting solution with zero downtime.- Developed multiple custom e-commerce websites for unique companies with unique requirements and strict regulations.### VanNoppen Marketing — *Principal Software Engineer*Full-Service Marketing Agency — JUNE 2010 - APRIL 2023- Managed, developed, and launched multiple projects in parallel for a wide variety of companies.- Integrated projects with numerous platforms including HubSpot, Facebook, Instagram, and Google services.- Managed multiple hosting environments including AWS, Heroku, and Linode (Docker).## Recent Projects### 3D Furniture Viewer — *Full-Stack Development, 3D Engineering*Craftmaster Furniture — JULY 2024 - CURRENT- Built a fully in-house 3D furniture customization system with real-time fabric draping across 1,000+ materials using Three.js and Django.- Eliminated dependency on expensive third-party 3D vendors, delivering the solution at a fraction of the cost.### Portal & Reporting Modernization — *Solutions Architecture, Full-Stack Development*Craftmaster Furniture — JULY 2024 - CURRENT- Migrated internal and external portals from a legacy IBM iSeries system to a modern Linux, Django, and PostgreSQL stack.- Integrated AI-powered reporting and insights, replacing outdated reporting workflows and reducing time spent by sales reps and sales and marketing teams.
added resume/generate.js
@@ -0,0 +1,131 @@const fs = require("fs");const path = require("path");const { chromium } = require("playwright");const { marked } = require("marked");const matter = require("gray-matter");const RESUME_DIR = __dirname;const CONTENT_PATH = path.join(RESUME_DIR, "content.md");const TEMPLATE_PATH = path.join(RESUME_DIR, "template.html");const OUTPUT_PATH = path.join(  RESUME_DIR,  "..",  "public",  "static",  "pdfs",  "resume-isaac-bythewood.pdf");function renderMarkdownBody(markdown) {  const renderer = new marked.Renderer();  renderer.heading = function ({ tokens, depth }) {    const text = this.parser.parseInline(tokens);    if (depth === 2) {      const note = text.includes("Experience") || text.includes("Projects")        ? ' <span class="section-note">— See LinkedIn for more</span>'        : "";      return `<h2>${text}${note}</h2>`;    }    if (depth === 3) {      return `<h3>${text}</h3>`;    }    return `<h${depth}>${text}</h${depth}>`;  };  renderer.paragraph = function ({ tokens }) {    const text = this.parser.parseInline(tokens);    if (      text.match(        /^[A-Z].*\u2014\s*(JANUARY|FEBRUARY|MARCH|APRIL|MAY|JUNE|JULY|AUGUST|SEPTEMBER|OCTOBER|NOVEMBER|DECEMBER)/i      )    ) {      return `<div class="meta">${text}</div>`;    }    return `<p>${text}</p>`;  };  marked.setOptions({ renderer });  // Parse markdown, then wrap each h3 + meta + ul group in an entry div  let html = marked.parse(markdown);  html = html.replace(    /(<h3>[\s\S]*?)(?=<h3>|<h2>|$)/g,    '<div class="entry">$1</div>'  );  return html;}function buildHtml(frontmatter, body) {  let template = fs.readFileSync(TEMPLATE_PATH, "utf-8");  const markdownHtml = renderMarkdownBody(body);  const linksHtml = frontmatter.links    .map((l) => `<a href="${l.url}">${l.label}</a>`)    .join("\n");  const skillsHtml = frontmatter.skills    .map((s) => `<li>${s}</li>`)    .join("\n");  const techHtml = frontmatter.technologies    .map((t) => `<li>${t}</li>`)    .join("\n");  const eduHtml = frontmatter.education    .map(      (e) =>        `<div class="education-entry"><span class="school">${e.institution},</span> ${e.years}<br>${e.degree}</div>`    )    .join("\n");  template = template    .replace(/\{\{name\}\}/g, frontmatter.name)    .replace(/\{\{title\}\}/g, frontmatter.title)    .replace(/\{\{summary\}\}/g, frontmatter.summary)    .replace(/\{\{location\}\}/g, frontmatter.location)    .replace(/\{\{phone\}\}/g, frontmatter.phone)    .replace(/\{\{email\}\}/g, frontmatter.email)    .replace(/\{\{links\}\}/g, linksHtml)    .replace(/\{\{skills\}\}/g, skillsHtml)    .replace(/\{\{technologies\}\}/g, techHtml)    .replace(/\{\{education\}\}/g, eduHtml)    .replace(/\{\{body\}\}/g, markdownHtml);  return template;}async function generatePdf() {  const raw = fs.readFileSync(CONTENT_PATH, "utf-8");  const { data: frontmatter, content: body } = matter(raw);  const html = buildHtml(frontmatter, body);  const launchOptions = {};  // Use system Chromium if PLAYWRIGHT_CHROMIUM_PATH is set (e.g. in Alpine Docker)  if (process.env.PLAYWRIGHT_CHROMIUM_PATH) {    launchOptions.executablePath = process.env.PLAYWRIGHT_CHROMIUM_PATH;  }  const browser = await chromium.launch(launchOptions);  const page = await browser.newPage({    viewport: { width: 816, height: 1056 },  });  await page.setContent(html, { waitUntil: "networkidle" });  await page.pdf({    path: OUTPUT_PATH,    format: "Letter",    printBackground: true,    margin: { top: 0, right: 0, bottom: 0, left: 0 },  });  await browser.close();  console.log(`Resume PDF generated: ${OUTPUT_PATH}`);}generatePdf().catch((err) => {  console.error("Failed to generate resume:", err);  process.exit(1);});
added resume/template.html
@@ -0,0 +1,264 @@<!DOCTYPE html><html lang="en"><head><meta charset="UTF-8"><style>  @page {    size: letter;    margin: 0;  }  * {    margin: 0;    padding: 0;    box-sizing: border-box;  }  body {    font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;    font-size: 9.5pt;    line-height: 1.35;    color: #1a1a1a;    width: 816px;    height: 1056px;    overflow: hidden;    -webkit-print-color-adjust: exact;    print-color-adjust: exact;  }  .page {    position: relative;    width: 816px;    height: 1056px;    overflow: hidden;  }  /* Sidebar - right column, absolutely positioned */  .sidebar {    position: absolute;    top: 0;    right: 0;    width: 240px;    height: 1056px;    background: #1e293b;    color: #e2e8f0;    padding: 0;    display: flex;    flex-direction: column;  }  .sidebar .contact {    background: #2563eb;    padding: 36px 24px 20px 24px;  }  .sidebar .contact .title {    font-size: 11pt;    font-weight: 700;    margin-bottom: 4px;  }  .sidebar .contact .location {    font-size: 9pt;    margin-bottom: 8px;    color: #dbeafe;  }  .sidebar .contact .phone,  .sidebar .contact .email {    font-size: 9pt;    color: #fff;  }  .sidebar .contact .phone {    font-weight: 700;    margin-bottom: 2px;  }  .sidebar .contact a {    color: #fff;    text-decoration: none;  }  .sidebar-content {    padding: 14px 24px;    display: flex;    flex-direction: column;    gap: 12px;  }  .sidebar h4 {    font-size: 9.5pt;    font-weight: 700;    text-transform: uppercase;    letter-spacing: 0.5px;    color: #94a3b8;    border-bottom: 1px solid #334155;    padding-bottom: 3px;    margin-bottom: 4px;  }  .sidebar .links a {    display: block;    font-size: 9pt;    color: #93c5fd;    text-decoration: none;    margin-bottom: 1px;  }  .sidebar .skills-list,  .sidebar .tech-list {    list-style: none;    padding: 0;  }  .sidebar .skills-list li {    font-size: 9pt;    margin-bottom: 1px;    color: #cbd5e1;  }  .sidebar .tech-list li {    display: inline;    font-size: 9pt;    color: #cbd5e1;  }  .sidebar .tech-list li:not(:last-child)::after {    content: ", ";  }  .sidebar .education-entry {    font-size: 9pt;    color: #cbd5e1;  }  .sidebar .education-entry .school {    font-weight: 700;    color: #e2e8f0;  }  /* Main content - left column */  .main {    margin-right: 240px;    padding: 36px 32px 36px 38px;    height: 1056px;    overflow: hidden;  }  .main h1 {    font-size: 26pt;    font-weight: 700;    line-height: 1.1;    margin-bottom: 5px;    color: #111;  }  .main .summary {    font-size: 9.5pt;    color: #444;    margin-bottom: 14px;    line-height: 1.4;  }  .main h2 {    font-size: 10.5pt;    font-weight: 700;    color: #2563eb;    text-transform: uppercase;    letter-spacing: 0.5px;    border-bottom: 1px solid #2563eb;    padding-bottom: 2px;    margin-bottom: 8px;    margin-top: 12px;  }  .main h2:first-of-type {    margin-top: 0;  }  .main h2 .section-note {    font-size: 8.5pt;    font-weight: 400;    text-transform: none;    letter-spacing: 0;    color: #2563eb;  }  .entry {    margin-bottom: 8px;  }  .entry h3 {    font-size: 10.5pt;    font-weight: 700;    color: #111;    margin-bottom: 1px;  }  .entry h3 em {    font-weight: 400;    font-style: italic;  }  .entry .meta {    font-size: 8.5pt;    color: #666;    margin-bottom: 3px;  }  .entry ul {    padding-left: 16px;    margin: 0;  }  .entry li {    font-size: 9pt;    margin-bottom: 1px;    color: #333;    line-height: 1.35;  }</style></head><body>  <div class="page">    <div class="main">      <h1>{{name}}</h1>      <p class="summary">{{summary}}</p>      {{body}}    </div>    <div class="sidebar">      <div class="contact">        <div class="title">{{title}}</div>        <div class="location">{{location}}</div>        <div class="phone">{{phone}}</div>        <div class="email"><a href="mailto:{{email}}">{{email}}</a></div>      </div>      <div class="sidebar-content">        <div class="links-section">          <h4>Links</h4>          <div class="links">            {{links}}          </div>        </div>        <div class="skills-section">          <h4>Skills</h4>          <ul class="skills-list">            {{skills}}          </ul>        </div>        <div class="tech-section">          <h4>Technologies</h4>          <ul class="tech-list">            {{technologies}}          </ul>        </div>        <div class="education-section">          <h4>Education</h4>          {{education}}        </div>      </div>    </div>  </div></body></html>
modified yarn.lock
@@ -386,6 +386,13 @@  dependencies:    tslib "^2.8.0"argparse@^1.0.7:  version "1.0.10"  resolved "https://registry.yarnpkg.com/argparse/-/argparse-1.0.10.tgz#bcd6791ea5ae09725e17e5ad988134cd40b3d911"  integrity sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==  dependencies:    sprintf-js "~1.0.2"baseline-browser-mapping@^2.9.0:  version "2.10.0"  resolved "https://registry.yarnpkg.com/baseline-browser-mapping/-/baseline-browser-mapping-2.10.0.tgz#5b09935025bf8a80e29130251e337c6a7fc8cbb9"
@@ -457,16 +464,56 @@ escalade@^3.2.0:  resolved "https://registry.yarnpkg.com/escalade/-/escalade-3.2.0.tgz#011a3f69856ba189dffa7dc8fcce99d2a87903e5"  integrity sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==esprima@^4.0.0:  version "4.0.1"  resolved "https://registry.yarnpkg.com/esprima/-/esprima-4.0.1.tgz#13b04cdb3e6c5d19df91ab6987a8695619b0aa71"  integrity sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==extend-shallow@^2.0.1:  version "2.0.1"  resolved "https://registry.yarnpkg.com/extend-shallow/-/extend-shallow-2.0.1.tgz#51af7d614ad9a9f610ea1bafbb989d6b1c56890f"  integrity sha512-zCnTtlxNoAiDc3gqY2aYAWFx7XWWiasuF2K8Me5WbN8otHKTUKBwjPtNpRs/rbUZm7KxWAaNj7P1a/p52GbVug==  dependencies:    is-extendable "^0.1.0"fsevents@2.3.2:  version "2.3.2"  resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-2.3.2.tgz#8a526f78b8fdf4623b709e0b975c52c24c02fd1a"  integrity sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==gensync@^1.0.0-beta.2:  version "1.0.0-beta.2"  resolved "https://registry.yarnpkg.com/gensync/-/gensync-1.0.0-beta.2.tgz#32a6ee76c3d7f52d46b2b1ae5d93fea8580a25e0"  integrity sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==gray-matter@^4.0.3:  version "4.0.3"  resolved "https://registry.yarnpkg.com/gray-matter/-/gray-matter-4.0.3.tgz#e893c064825de73ea1f5f7d88c7a9f7274288798"  integrity sha512-5v6yZd4JK3eMI3FqqCouswVqwugaA9r4dNZB1wwcmrD02QkV5H0y7XBQW8QwQqEaZY1pM9aqORSORhJRdNK44Q==  dependencies:    js-yaml "^3.13.1"    kind-of "^6.0.2"    section-matter "^1.0.0"    strip-bom-string "^1.0.0"is-extendable@^0.1.0:  version "0.1.1"  resolved "https://registry.yarnpkg.com/is-extendable/-/is-extendable-0.1.1.tgz#62b110e289a471418e3ec36a617d472e301dfc89"  integrity sha512-5BMULNob1vgFX6EjQw5izWDxrecWK9AM72rugNr0TFldMOi0fj6Jk+zeKIt0xGj4cEfQIJth4w3OKWOJ4f+AFw=="js-tokens@^3.0.0 || ^4.0.0", js-tokens@^4.0.0:  version "4.0.0"  resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-4.0.0.tgz#19203fb59991df98e3a287050d4647cdeaf32499"  integrity sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==js-yaml@^3.13.1:  version "3.14.2"  resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.14.2.tgz#77485ce1dd7f33c061fd1b16ecea23b55fcb04b0"  integrity sha512-PMSmkqxr106Xa156c2M265Z+FTrPl+oxd/rgOQy2tijQeK5TxQ43psO1ZCwhVOSdnn+RzkzlRz/eY4BgJBYVpg==  dependencies:    argparse "^1.0.7"    esprima "^4.0.0"jsesc@^3.0.2:  version "3.1.0"  resolved "https://registry.yarnpkg.com/jsesc/-/jsesc-3.1.0.tgz#74d335a234f67ed19907fdadfac7ccf9d409825d"
@@ -477,6 +524,11 @@ json5@^2.2.3:  resolved "https://registry.yarnpkg.com/json5/-/json5-2.2.3.tgz#78cd6f1a19bdc12b73db5ad0c61efd66c1e29283"  integrity sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==kind-of@^6.0.0, kind-of@^6.0.2:  version "6.0.3"  resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-6.0.3.tgz#07c05034a6c349fa06e24fa35aa76db4580ce4dd"  integrity sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==loose-envify@^1.4.0:  version "1.4.0"  resolved "https://registry.yarnpkg.com/loose-envify/-/loose-envify-1.4.0.tgz#71ee51fa7be4caec1a63839f7e682d8132d30caf"
@@ -491,6 +543,11 @@ lru-cache@^5.1.1:  dependencies:    yallist "^3.0.2"marked@^17.0.6:  version "17.0.6"  resolved "https://registry.yarnpkg.com/marked/-/marked-17.0.6.tgz#2a97586a272d3be5880f198e020b74ad27cf86ba"  integrity sha512-gB0gkNafnonOw0obSTEGZTT86IuhILt2Wfx0mWH/1Au83kybTayroZ/V6nS25mN7u8ASy+5fMhgB3XPNrOZdmA==ms@^2.1.3:  version "2.1.3"  resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.3.tgz#574c8138ce1d2b5861f0b44579dbadd60c6615b2"
@@ -538,6 +595,20 @@ picocolors@^1.0.0, picocolors@^1.1.1:  resolved "https://registry.yarnpkg.com/picocolors/-/picocolors-1.1.1.tgz#3d321af3eab939b083c8f929a1d12cda81c26b6b"  integrity sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==playwright-core@1.59.1:  version "1.59.1"  resolved "https://registry.yarnpkg.com/playwright-core/-/playwright-core-1.59.1.tgz#d8a2b28bcb8f2bd08ef3df93b02ae83c813244b2"  integrity sha512-HBV/RJg81z5BiiZ9yPzIiClYV/QMsDCKUyogwH9p3MCP6IYjUFu/MActgYAvK0oWyV9NlwM3GLBjADyWgydVyg==playwright@^1.59.1:  version "1.59.1"  resolved "https://registry.yarnpkg.com/playwright/-/playwright-1.59.1.tgz#f7b0ca61637ae25264cec370df671bbe1f368a4a"  integrity sha512-C8oWjPR3F81yljW9o5OxcWzfh6avkVwDD2VYdwIGqTkl+OGFISgypqzfu7dOe4QNLL2aqcWBmI3PMtLIK233lw==  dependencies:    playwright-core "1.59.1"  optionalDependencies:    fsevents "2.3.2"postcss@8.4.31:  version "8.4.31"  resolved "https://registry.yarnpkg.com/postcss/-/postcss-8.4.31.tgz#92b451050a9f914da6755af352bdc0192508656d"
@@ -593,6 +664,14 @@ scheduler@^0.27.0:  resolved "https://registry.yarnpkg.com/scheduler/-/scheduler-0.27.0.tgz#0c4ef82d67d1e5c1e359e8fc76d3a87f045fe5bd"  integrity sha512-eNv+WrVbKu1f3vbYJT/xtiF5syA5HPIMtf9IgY/nKg0sWqzAUEvqY/xm7OcZc/qafLx/iO9FgOmeSAp4v5ti/Q==section-matter@^1.0.0:  version "1.0.0"  resolved "https://registry.yarnpkg.com/section-matter/-/section-matter-1.0.0.tgz#e9041953506780ec01d59f292a19c7b850b84167"  integrity sha512-vfD3pmTzGpufjScBh50YHKzEu2lxBWhVEHsNGoEXmCmn2hKGfeNLYMzCJpe8cD7gqX7TJluOVpBkAequ6dgMmA==  dependencies:    extend-shallow "^2.0.1"    kind-of "^6.0.0"semver@^6.3.1:  version "6.3.1"  resolved "https://registry.yarnpkg.com/semver/-/semver-6.3.1.tgz#556d2ef8689146e46dcea4bfdd095f3434dffcb4"
@@ -642,6 +721,16 @@ source-map-js@^1.0.2:  resolved "https://registry.yarnpkg.com/source-map-js/-/source-map-js-1.2.1.tgz#1ce5650fddd87abc099eda37dcff024c2667ae46"  integrity sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==sprintf-js@~1.0.2:  version "1.0.3"  resolved "https://registry.yarnpkg.com/sprintf-js/-/sprintf-js-1.0.3.tgz#04e6926f662895354f3dd015203633b857297e2c"  integrity sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==strip-bom-string@^1.0.0:  version "1.0.0"  resolved "https://registry.yarnpkg.com/strip-bom-string/-/strip-bom-string-1.0.0.tgz#e5211e9224369fbb81d633a2f00044dc8cedad92"  integrity sha512-uCC2VHvQRYu+lMh4My/sFNmF2klFymLX1wHJeXnbEJERpV/ZsVuonzerjfrGpIGF7LBVa1O7i9kjiWvJiFck8g==styled-jsx@5.1.6:  version "5.1.6"  resolved "https://registry.yarnpkg.com/styled-jsx/-/styled-jsx-5.1.6.tgz#83b90c077e6c6a80f7f5e8781d0f311b2fe41499"