Skip to content

Instantly share code, notes, and snippets.

@nberlette
Last active October 6, 2023 23:20
Show Gist options
  • Save nberlette/3fafd6026344f3c2013c2f6d41813b48 to your computer and use it in GitHub Desktop.
Save nberlette/3fafd6026344f3c2013c2f6d41813b48 to your computer and use it in GitHub Desktop.
Using SVG <foreignObject /> to render an HTML document as an image
<!DOCTYPE html>
<html>
<head>
<title>image.ts documentation</title>
<style>
html,
body {
--font-mono: "IBM Plex Mono", "Dank Mono", "Operator Mono", "Fira Code", 'Courier New', Courier, ui-monospace, monospace;
--font-sans: "IBM Plex Sans", "Lucida Grande", Arial, Helvetica, ui-sans-serif, sans-serif;
--font-serif: "IBM Plex Serif", Georgia, Times, "Times New Roman", ui-serif, serif;
/* background-color: #101010; */
color-scheme: dark;
font-family: var(--font-mono);
}
div {
margin: 0.5rem;
}
.color-555 {
color: #a8d3c2cc;
display: table-row;
}
.color-a0a,
.color-red {
color: indianred;
font-family: var(--font-mono) !important;
}
.color-a0a h3 {
display: inline-block;
font-family: var(--font-mono);
}
.color-a0a-2 {
color: rgba(254, 139, 38, 0.7);
font-weight: bold;
font-family: var(--font-mono) !important;
}
.color-5ff {
color: #5ff;
font-weight: bold;
font-family: var(--font-mono);
;
}
.color-purple {
color: rgb(123, 123, 247);
}
section {
margin: 1rem 0;
}
:root {
--color-keyword: #ffa3d3;
--color-variable: #88fefe;
--color-constant: #ff6287;
--color-identifier: #ffb15f;
--color-class: #e082ff;
--color-boolean: #b6ef9c;
--color-number: #ffde79;
--color-string: #c1ffa4;
--color-regex: #99ccff;
--color-comment: #a2a2a2;
--color-deprecated: #aaaaaaaa;
--color-jsdoc: #decfba;
--color-function: #d572f7;
--color-punctuation: #a8d3c2cc;
--color-type: #5ff;
}
.argument {
color: var(--color-class);
}
.keyword {
color: var(--color-keyword);
}
.boolean {
color: var(--color-boolean);
}
.number {
color: var(--color-number);
}
.regex {
color: var(--color-regex);
}
.comment {
color: var(--color-comment);
}
.deprecated {
color: var(--color-deprecated);
}
.variable {
color: var(--color-variable);
}
.constant {
color: var(--color-constant);
}
.identifier {
color: var(--color-identifier);
}
.string {
color: var(--color-string);
}
.class {
color: var(--color-class);
}
.jsdoc,
.comment {
color: var(--color-jsdoc);
}
.function {
color: var(--color-function);
}
.punctuation {
color: var(--color-punctuation);
}
.type {
color: var(--color-type);
}
.inline-block {
display: inline-block;
}
.m-0 {
margin: 0;
}
.p-0 {
padding: 0;
}
section:not(:first-child) {
border-top: 1px dashed #fff3;
margin-top: 1.75rem;
padding-top: 1.5rem;
}
</style>
</head>
<body>
<div>
<section>
<h2><span style="color:#ffa3d3">class</span> <strong>Image</strong></h2>
<p class="comment">The <span class="identifier">Image</span> API represents a single image scraped from the live
feed It integrates with the Deno KV data store and the underlying file-system to provide a unified API for
reading/writing the image data. This class provides I/O functionality for reading/writing the data to the KV
data store as well as the underlying file-system.</p>
<p class="comment">It's important to note our API's file naming convention. Each image is named after the date and
time it was taken, in UTC. The date is used as the folder name, and the time is used as the file name:</p>
<pre
class="jsdoc m-0 p-0"><code>`2023-07-09/12_34_56.jpg` → <span style="color:#99ccff">2023-07-09T12:34:56Z</span></code></pre>
</section>
<br>
<hr><br>
<section>
<h4 class="identifier inline-block m-0 p-0"><a href="#constructor" id="constructor" title="constructor"
class="identifier">constructor</a></h4><span
class="punctuation"></span><span>(</span><br /><span>  </span><span style="color:#ffa3d3">date: </span><span
style="color:#c1ffa4">string</span> | <span style="color:#c1ffa4">number</span> | <span
style="color:#99ccff">Date</span>,<br>  <span class="argument">data: </span><span
class="type">BufferSource</span><span style="opacity:0.5"> | <span class="type">null</span></span>,<br>  <span
style="color:#ffa3d3">path</span><span class="punctuation">?: </span><span class="type">string</span> | <span
class="type">URL</span><span style="opacity:0.5"> | <span style="color:#c1ffa4">null</span></span>,<br>  <span
style="color:#ffa3d3">latest</span><span class="punctuation">?:</span> <span
style="color:#c1ffa4">boolean</span> <span style="opacity:0.5">| <span
style="color:#c1ffa4">undefined</span></span>,<br><span class="punctuation">);</span><br />
</section>
<br>
<section>
<em class="keyword readonly">readonly</em><span> </span>
<h4 class="identifier inline-block m-0 p-0"><a href="#buffer" id="buffer" title="Image.buffer"
class="identifier">buffer</a></h4>
<span class="punctuation">: </span><span style="color:#99ccff">ArrayBuffer</span> | <span
style="color:#c1ffa4">null</span><br />   <span class="comment">The underlying `ArrayBuffer` that contains this
image's data. If the</span><br />   <span class="comment">image hasn't been loaded yet, this value will be
`null`.</span>
</section>
<section>
<em class="keyword readonly">readonly</em><span> </span>
<h4 class="identifier inline-block m-0 p-0"><a href="#data" id="data" title="Image.data"
class="identifier">data</a></h4><span class="punctuation">: </span><span
style="color:#99ccff">Uint8Array</span> | <span style="color:#c1ffa4">null</span><br />   <span
class="comment">The underlying {@link Image.buffer} data wrapped
in a `Uint8Array`. If the</span><br />   <span class="comment">image hasn't been loaded yet, this value will be
`null`.</span>
</section>
<section>
<em class="keyword readonly">readonly</em><span> </span>
<h4 class="identifier inline-block m-0 p-0"><a href="#date" id="date" title="Image.date"
class="identifier">date</a></h4><span class="punctuation">: </span><span
style="color:#99ccff">Date</span><br />   <span class="comment">The timestamp
reflecting the time of the image's creation.</span>
</section>
<section>
<em class="keyword readonly">readonly</em><span> </span>
<h4 class="identifier inline-block m-0 p-0"><a href="#size" id="size" title="Image.size"
class="identifier">size</a></h4><span class="punctuation">: </span><span
style="color:#c1ffa4">number</span><br />   <span class="comment">The size of
the image's underlying data buffer, in bytes.</span>
</section>
<section>
<em class="keyword readonly">readonly</em><span> </span>
<h4 class="identifier inline-block m-0 p-0"><a href="#byteLength" id="byteLength" title="Image.byteLength"
class="identifier">byteLength</a></h4><span class="punctuation">: </span><span
style="color:#c1ffa4">number</span><br />   <span class="comment">An alias for {@link Image.size}, reflecting
the image's size.</span>
</section>
<section>
<em class="keyword readonly">readonly</em><span> </span>
<h4 class="identifier inline-block m-0 p-0"><a href="#key" id="key" title="Image.key" class="identifier">key</a>
</h4><span class="punctuation">: </span><span style="color:#99ccff">Deno.KvKey</span><br />   <span
class="comment">The key
used for persisting the image's data a in Deno KV database.</span>
</section>
<section>
<em class="keyword readonly">readonly</em><span> </span>
<h4 class="identifier inline-block m-0 p-0"><a href="#path" id="path" title="Image.path"
class="identifier">path</a></h4>:
<span style="color:#c1ffa4">string</span><br />   <span class="comment">The path to the image's `JPEG` file on the
file-system.</span><br /><small>  <span class="comment">⚠️ <strong>Note</strong>: <em>this file isn't guaranteed
to exist, and may also be relative</em>.</span></small>
</section>
<br>
<section>
<em class="keyword async">async</em><span> </span>
<h4 class="identifier inline-block m-0 p-0"><a href="#read" id="read" title="read" class="identifier">read</a>
</h4><span class="punctuation">(): </span><span class="type">Promise</span><span
class="punctuation">&lt;</span><span style="color:#99ccff">Uint8Array</span><span
class="punctuation">&gt;</span><br />   <span class="comment">Reads
the image's data from the KV store.</span>
</section>
<section>
<em class="keyword async">async</em><span> </span>
<h4 class="identifier inline-block m-0 p-0"><a href="#write" id="write" title="write" class="identifier">write</a>
</h4><span class="punctuation">(): </span><span class="type">Promise</span><span
class="punctuation">&lt;</span><em style="color:#fa0">this</em><span class="punctuation">&gt;</span><br />
  <span class="comment">Writes the
image's data to the KV store.</span>
</section>
<section>
<em class="keyword async">async</em><span> </span>
<h4 class="identifier inline-block m-0 p-0"><a href="#exists" id="exists" title="exists"
class="identifier">exists</a></h4><span class="punctuation">(): </span><span class="type">Promise</span><span
class="punctuation">&lt;</span><span style="color:#c1ffa4">boolean</span><span
class="punctuation">&gt;</span><br />   <span class="comment">Checks
whether or not the image's data exists in the KV store.</span>
</section>
<section>
<em class="keyword async">async</em><span> </span>
<h4 class="identifier inline-block m-0 p-0"><a href="#delete" id="delete" title="delete"
class="identifier">delete</a></h4><span class="punctuation">(): </span><span class="type">Promise</span><span
class="punctuation">&lt;</span><span style="color:#c1ffa4">void</span><span
class="punctuation">&gt;</span><br />   <span class="comment">Deletes the
image's data from the KV store.</span>
</section>
<br>
<section>
<em class="keyword async">async</em><span> </span>
<h4 class="identifier inline-block m-0 p-0"><a href="#readFile" id="readFile" title="readFile"
class="identifier">readFile</a></h4>
<span class="punctuation">(</span><span style="color:#ffa3d3">path</span>?: <span
style="color:#c1ffa4">string</span> | <span style="color:#99ccff">URL</span><span class="punctuation">):
</span><span style="color:#99ccff">Promise</span>&lt;<span style="color:#99ccff">Uint8Array</span>&gt;<br />
  <span class="comment">Reads the file from the file-system, optionally at a custom path.</span>
</section>
<section>
<em class="keyword async">async</em><span> </span>
<h4 class="identifier inline-block m-0 p-0"><a href="#writeFile" id="writeFile" title="writeFile"
class="identifier">writeFile</a>
</h4><span class="punctuation">(</span><span style="color:#ffa3d3">path</span>?: <span
style="color:#c1ffa4">string</span> | <span style="color:#99ccff">URL</span><span class="punctuation">):
</span><span style="color:#99ccff">Promise</span>&lt;<em style="color:#fa0">this</em>&gt;<br />   <span
class="comment">Write the image to the file-system, optionally at a custom path.</span>
</section>
<section>
<h4 class="identifier inline-block m-0 p-0"><a href="#fileExists" id="fileExists" title="fileExists"
class="identifier">fileExists</a></h4><span class="punctuation">(</span><span
style="color:#ffa3d3">path</span>?: <span style="color:#c1ffa4">string</span> | <span
style="color:#99ccff">URL</span><span class="punctuation">): </span><span
style="color:#c1ffa4">boolean</span><br />   <span class="comment">Check if an image exists in a file-system, at
an optional custom path.</span>
</section>
<section>
<em class="keyword async">async</em><span> </span>
<h4 class="identifier inline-block m-0 p-0"><a href="#deleteFile" id="deleteFile" title="deleteFile"
class="identifier">deleteFile</a></h4><span class="punctuation">(</span><span
style="color:#ffa3d3">path</span>?: <span style="color:#c1ffa4">string</span> | <span
style="color:#99ccff">URL</span><span class="punctuation">): </span><span
style="color:#99ccff">Promise</span>&lt;<span style="color:#c1ffa4">boolean</span>&gt;<br />   <span
class="comment">Delete the image from the file-system, optionally at a custom path.</span>
</section>
<br>
<section>
<h4 class="identifier inline-block m-0 p-0"><a href="#equals" id="equals" title="equals"
class="identifier">equals</a></h4><span class="punctuation">(</span><span style="color:#ffa3d3">that</span>:
<span style="color:#99ccff">Image</span> |
<span style="color:#99ccff">BufferSource</span><span class="punctuation">): </span><span
style="color:#c1ffa4">boolean</span><br />   <span class="comment">Check if the image's data is equal to another
image's data.</span>
</section>
<section>
<h4 class="identifier inline-block m-0 p-0"><a href="#toFile" id="toFile" title="toFile"
class="identifier">toFile</a></h4><span class="punctuation">(</span><span style="color:#ffa3d3">name</span>?:
<span style="color:#c1ffa4">string</span><span class="punctuation">): </span><span
style="color:#99ccff">File</span><br />  <span class="comment">Returns a `File` object for the image.</span>
</section>
<section>
<h4 class="identifier inline-block m-0 p-0"><a href="#toJSON" id="toJSON" title="toJSON"
class="identifier">toJSON</a></h4><span class="punctuation">(): </span><span class="type">Record&lt;string,
unknown&gt;</span><br />   <span class="comment">Returns a JSON representation of the image.</span>
</section>
<section>
<h4 class="identifier inline-block m-0 p-0"><a href="#toString" id="toString" title="toString"
class="identifier">toString</a></h4>
<span class="punctuation">(): </span><span class="type">string</span>
<p class="comment">Returns the image's file-system path string.</p>
</section>
<br>
<hr><br>
<section>
<em class="keyword static">static</em><span> </span>
<h4 class="identifier inline-block m-0 p-0"><a href="#folderName" id="folderName" title="folderName"
class="identifier">folderName</a></h4><span class="punctuation">: </span><span class="type">string</span>
<p class="comment">The name of the folder where the images are stored.</p>
<br>
<em class="keyword static">static</em><span> </span>
<h4 class="identifier inline-block m-0 p-0"><a href="#hashTableKey" id="hashTableKey" title="hashTableKey"
class="identifier">hashTableKey</a></h4><span class="punctuation">: </span><span class="type">string</span>
<p class="comment">The Deno KV key prefix for the image hash-to-date index.</p>
<br>
<em class="keyword static">static</em><span> </span>
<h4 class="identifier inline-block m-0 p-0"><a href="#latestImageName" id="latestImageName"
title="latestImageName" class="identifier">latestImageName</a></h4><span class="punctuation">: </span><span
class="type">string</span>
<p class="comment">The name of the file that contains the most recent image.</p>
</section>
<br>
<section><span style="color:#ffa3d3">static async <strong>fromDate</strong></span>(<br>  <span
style="color:#ffa3d3">date: </span><span style="color:#c1ffa4">string</span> | <span
style="color:#c1ffa4">number</span> | <span style="color:#99ccff">Date</span>,<br>  latest<span
style="color:#ffa3d3">?</span>: <span style="color:#c1ffa4">boolean</span><br><span class="punctuation">):
</span><span class="type">Promise</span><span class="punctuation">&lt;</span><span
class="identifier">Image</span><span class="punctuation">&gt;</span>
<p class="comment">Creates a new image from an existing scrape event's timestamp. For this to work as intended,
the image must have already been scraped and saved to the underlying file-system or KV data store.</p>
</section>
<section>
<span style="color:#ffa3d3">static async <strong>fromFile</strong></span>(<br>  <span
style="color:#ffa3d3">path</span>: <span style="color:#c1ffa4">string</span> | <span
style="color:#99ccff">URL</span>,<br>  <span style="color:#ffa3d3">latest</span>?: <span
style="color:#c1ffa4">boolean</span><br><span class="punctuation">): </span><span
class="type">Promise</span><span class="punctuation">&lt;</span><span class="identifier">Image</span><span
class="punctuation">&gt;</span>
<p class="comment">Creates a new image from a file on the file-system.</p>
</section>
<section>
<span style="color:#ffa3d3">static async <strong>fromReader</strong></span>(<br>
  <span style="color:#ffa3d3">reader: </span><span style="color:#99ccff">Deno.Reader</span>,<br>
  <span style="color:#ffa3d3">latest</span>?: <span style="color:#c1ffa4">boolean</span>,<br><span
class="punctuation">): </span><span class="type">Promise</span><span class="punctuation">&lt;</span><span
class="identifier">Image</span><span class="punctuation">&gt;</span>
<p class="comment">Creates a new image from a <span class="type">Deno.Reader</span> stream.</p>
</section>
<section>
<span style="color:#ffa3d3">static async <strong>fromStream</strong></span>(<br>  <span
style="color:#ffa3d3">stream</span>: <span style="color:#99ccff">ReadableStream</span>&lt;<span
style="color:#99ccff">Uint8Array</span>&gt;,<br>  <span style="color:#ffa3d3">latest</span>?: <span
style="color:#c1ffa4">boolean</span><br><span class="punctuation">): </span><span
class="type">Promise</span><span class="punctuation">&lt;</span><span class="identifier">Image</span><span
class="punctuation">&gt;</span>
<p class="comment">Creates a new image from a `ReadableStream` of `Uint8Array` data, such as a `Response.body`
stream from a `fetch` request.</p>
</section>
<br>
<section>
<em class="keyword static">static</em><span> </span>
<h4 class="identifier inline-block m-0 p-0"><a href="#dateToPath" id="dateToPath" title="dateToPath"
class="identifier">dateToPath</a></h4><span class="punctuation">(</span><span
style="color:#ffa3d3">date</span>: <span style="color:#c1ffa4">string</span> | <span
style="color:#c1ffa4">number</span> | <span style="color:#99ccff">Date</span>, latest<span
style="color:#ffa3d3">?</span>: <span style="color:#c1ffa4">boolean</span><span class="punctuation">):
</span><span style="color:#c1ffa4">string</span>
<p class="comment">Converts an image's date to a path string.</p>
</section>
<section>
<em class="keyword static">static</em><span> </span>
<h4 class="identifier inline-block m-0 p-0"><a href="#pathToDate" id="pathToDate" title="pathToDate"
class="identifier">pathToDate</a></h4><span class="punctuation">(</span><span
style="color:#ffa3d3">path</span>: <span style="color:#c1ffa4">string</span> | <span
style="color:#99ccff">URL</span>, latest<span style="color:#ffa3d3">?</span>: <span
style="color:#c1ffa4">boolean</span><span class="punctuation">): </span><span style="color:#99ccff">Date</span>
<p class="comment">Converts an image's path to a date object.</p>
</section>
<section>
<em class="keyword static">static</em><span> </span>
<h4 class="identifier inline-block m-0 p-0"><a href="#hash" id="hash" title="hash" class="identifier">hash</a>
</h4><span class="punctuation">(</span><span style="color:#ffa3d3">data</span>: <span
style="color:#99ccff">BufferSource</span> | <span style="color:#99ccff">Image</span>, digest<span
style="color:#ffa3d3">?</span>: <span style="color:#b6ef9c">"hex"</span> | <span
style="color:#c1ffa4">undefined</span><span class="punctuation">): </span><span
style="color:#c1ffa4">string</span>;<br />
<em class="keyword static">static</em><span> </span>
<h4 class="identifier inline-block m-0 p-0"><a href="#hash" id="hash" title="hash" class="identifier">hash</a>
</h4><span class="punctuation">(</span><span style="color:#ffa3d3">data</span>: <span
style="color:#99ccff">BufferSource</span> | <span style="color:#99ccff">Image</span>, digest: <span
style="color:#b6ef9c">"array"</span><span class="punctuation">): </span><span
style="color:#c1ffa4">number</span>[]<br />
<em class="keyword static">static</em><span> </span>
<h4 class="identifier inline-block m-0 p-0"><a href="#hash" id="hash" title="hash" class="identifier">hash</a>
</h4><span class="punctuation">(</span><span style="color:#ffa3d3">data</span>: <span
style="color:#99ccff">BufferSource</span> | <span style="color:#99ccff">Image</span>, digest: <span
style="color:#b6ef9c">"buffer"</span><span class="punctuation">): </span><span
style="color:#99ccff">ArrayBuffer</span>
<p class="comment">Creates a unique SHA256 hash based on the given data.</p>
</section>
<br>
<hr><br>
<section>
<span style="color:#ffa3d3">type</span> <strong>TimeStamp</strong> = <span
style="color:#99ccff">TimeStampString</span> | <span style="color:#c1ffa4">number</span> | <span
style="color:#99ccff">Date</span><br /><br />
</section>
</div>
</body>
</html>
Display the source blob
Display the rendered blob
Raw
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment