diff --git a/data/benchmarking.ts b/data/benchmarking.ts index f801386..2e378de 100644 --- a/data/benchmarking.ts +++ b/data/benchmarking.ts @@ -5,7 +5,7 @@ * @run deno bench * @resource {https://docs.deno.com/runtime/manual/tools/benchmarker} Manual: Benchmarker tool * @resource {/http-requests} Example: HTTP Requests - * + * * When writing libraries, a very common task that needs to be done is * testing the speed of methods, usually against other libraries. Deno * provides an easy-to-use subcommand for this purpose. diff --git a/data/byte-manipulation.ts b/data/byte-manipulation.ts index 5ff43d9..0293d6d 100644 --- a/data/byte-manipulation.ts +++ b/data/byte-manipulation.ts @@ -3,7 +3,8 @@ * @difficulty beginner * @tags cli * @run - * @resource {$std/bytes} Doc: std/bytes + * @resource {https://jsr.io/@std/bytes} Doc: @std/bytes + * @dependency jsr:@std/bytes * * When working with lower-level data we often deal * with byte arrays in the form of Uint8Arrays. There @@ -11,23 +12,23 @@ * be done and are included with the standard library. */ -// Let's initialize some byte arrays +import { concat } from "@std/bytes/concat"; +import { repeat } from "@std/bytes/repeat"; +import { copy } from "@std/bytes/copy"; + const a = new Uint8Array([0, 1, 2, 3, 4]); const b = new Uint8Array([5, 6, 7, 8, 9]); const c = new Uint8Array([4, 5]); // We can concatenate two byte arrays using the -// concat method -import { concat } from "$std/bytes/concat.ts"; +// concat method. const d = concat([a, b]); console.log(d); // [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] -// Sometimes we need to repeat certain bytes -import { repeat } from "$std/bytes/repeat.ts"; +// Repeat can be used to repeat a chunk of bytes a specified number of times. console.log(repeat(c, 4)); // [4, 5, 4, 5, 4, 5, 4, 5] -// Sometimes we need to mutate a Uint8Array and need a copy -import { copy } from "$std/bytes/copy.ts"; +// We can also copy a chunk of bytes from one array to another. const cpy = new Uint8Array(5); console.log("Bytes copied:", copy(b, cpy)); // 5 console.log("Bytes:", cpy); // [5, 6, 7, 8, 9] diff --git a/data/checking-file-existence.ts b/data/checking-file-existence.ts index f2a039d..313581f 100644 --- a/data/checking-file-existence.ts +++ b/data/checking-file-existence.ts @@ -4,19 +4,18 @@ * @tags cli, deploy * @run --allow-read --allow-write * - * Sometimes we as developers think that we need to check - * if a file exists or not. More often than not, we are - * entirely wrong. + * Often one reaches to checking if a file exists before performing an operation + * on it. This is a common anti-pattern that can lead to race conditions. This + * example demonstrates how to avoid this anti-pattern. */ -// Let's say we wanted to create a folder if one doesn't -// already exist. Logically it makes sense to first verify -// that the folder exists, then try to create it right? -// Wrong. This will create a race condition where if a folder -// gets created in between when you check if the folder exists -// and when you create a folder, your program will crash. -// Instead, you should just create a folder and try to catch -// errors like so. +// You may want to create a folder if it does not exist. The naive way to do +// this is to check if the folder exists and then create it if it does not. +// This is an anti-pattern as it can lead to no folder being created if the +// folder is deleted between the check and the creation. +// +// Instead of checking for existence, you should simply try to create the +// folder and catch the error if it already exists. try { await Deno.mkdir("new_dir"); } catch (err) { @@ -25,11 +24,11 @@ try { } } -// This applies to almost every usecase. If you have a niche -// usecase that requires you to check for existence of a file -// without doing an filesystem operations other than that -// (which is quite rare), then you can simply lstat the file -// and catch the error. +// In some cases, you may still have to check if a file exists or not. For +// example you may want to avoid expensive work to compute the content of a file +// to be created, if the file already exists. +// In this case, you can call `Deno.lstat` to check if the file exists, and +// catch the `NotFound` error if it does not. try { await Deno.lstat("example.txt"); console.log("exists!"); @@ -37,5 +36,5 @@ try { if (!(err instanceof Deno.errors.NotFound)) { throw err; } - console.log("not exists!"); + console.log("does not exists!"); } diff --git a/data/command-line-arguments.ts b/data/command-line-arguments.ts index 9a0f523..3ec7eb1 100644 --- a/data/command-line-arguments.ts +++ b/data/command-line-arguments.ts @@ -4,7 +4,8 @@ * @tags cli * @run Deno Sushi --help --version=1.0.0 --no-color * @resource {https://deno.land/api?s=Deno.args} Doc: Deno.args - * @resource {$std/cli/parse_args.ts} Doc: std/cli + * @resource {https://jsr.io/@std/cli} Doc: std/cli + * @dependency jsr:@std/cli * * Command line arguments are often used to pass configuration options to a * program. @@ -17,7 +18,7 @@ console.log(`Hello ${name}, I like ${food}!`); // Often you want to parse command line arguments like `--foo=bar` into // structured data. This can be done using `std/cli`. -import { parseArgs } from "$std/cli/parse_args.ts"; +import { parseArgs } from "@std/cli/parse_args"; // The `parseArgs` function takes the argument list, and a list of options. In these // options you specify the types of the accepted arguments and possibly default diff --git a/data/dependency-management.ts b/data/dependency-management.ts index 26d9fe0..dd07fbe 100644 --- a/data/dependency-management.ts +++ b/data/dependency-management.ts @@ -5,23 +5,29 @@ * @resource {/import-export} Example: Importing & Exporting * @run * - * It is unwieldy to have to import the same remote module over and over again. - * Deno provides some conventions to make managing dependencies easier. + * It is unwieldy to have to specify version constraints for the same module + * over and over again in your code. Deno provides tools to make managing + * dependencies easier. */ -// File: ./deps.ts - -// The Deno ecosystem has a convention to re-export all remote dependencies from -// a deps.ts file at the root of the repo. This keeps remote dependencies -// organized, and in a single place. -export * as http from "$std/http/mod.ts"; -export * as path from "$std/path/mod.ts"; +/* File: ./deno.json +// The `deno.json` file acts like an import map, allowing you to specify +// aliases for remote modules. +{ + "imports": { + "@std/path": "jsr:@std/path@^0.220", + "@std/bytes": "jsr:@std/bytes@^0.220" + } +} +*/ // File: ./main.ts -// Other files can then import dependencies from the deps.ts file. +// Other files can import modules using the aliases specified in `deno.json`. +// deno-lint-ignore no-unused-vars +import * as path from "@std/path"; // deno-lint-ignore no-unused-vars -import { path } from "./deps.ts"; +import { concat } from "@std/bytes/concat"; -// Doing this makes package version upgrades really easy, as all external -// dependency specifiers live in the same file. +// Doing this makes package version upgrades really easy, as the version +// constraints for all dependencies are in one place. diff --git a/data/hex-base64-encoding.ts b/data/hex-base64-encoding.ts index 281a814..0f92f1b 100644 --- a/data/hex-base64-encoding.ts +++ b/data/hex-base64-encoding.ts @@ -3,6 +3,8 @@ * @difficulty beginner * @tags cli * @run + * @resource {https://jsr.io/@std/encoding} Doc: @std/encoding + * @dependency jsr:@std/encoding * * There are a few cases where it would be practical to encode * and decode between different string and array buffer formats. @@ -10,31 +12,25 @@ */ // The standard library provides hex and base64 encoding and decoding utilities -import * as base64 from "$std/encoding/base64.ts"; -import * as hex from "$std/encoding/hex.ts"; +import { decodeBase64, encodeBase64 } from "@std/encoding/base64"; +import { decodeHex, encodeHex } from "@std/encoding/hex"; -// We can easily encode a string or an array buffer into base64 using the base64.encode method. -const base64Encoded = base64.encode("somestringtoencode"); -console.log(base64.encode(new Uint8Array([1, 32, 67, 120, 19]))); +// We can easily encode a string into base64 using the encodeBase64 method. +const base64Encoded = encodeBase64("somestringtoencode"); +console.log(base64Encoded); // "c29tZXN0cmluZ3RvZW5jb2Rl" -// We can then decode base64 into a byte array using the decode method. -const base64Decoded = base64.decode(base64Encoded); +// We can then decode base64 into a byte array using the decodeBase64 method. +const base64Decoded = decodeBase64(base64Encoded); +console.log(base64Decoded); // Uint8Array(18) [ 115, 111, 109, 101, 115, ... ] // If we want to get the value as a string we can use the built-in TextDecoder. -// We will use these a lot so we can store them in variables to reuse them. -const textEncoder = new TextEncoder(); const textDecoder = new TextDecoder(); -console.log(textDecoder.decode(base64Decoded)); +console.log(textDecoder.decode(base64Decoded)); // "somestringtoencode" -// To encode hex, we always use array buffers. -// To use a string as an input we can encode our text. -const arrayBuffer = textEncoder.encode("somestringtoencode"); -const hexEncoded = hex.encode(arrayBuffer); -console.log(hexEncoded); - -// To read our hex values as a string, we can decode the buffer. -console.log(textDecoder.decode(hexEncoded)); +// We can also encode a string into hex using the encodeHex method. +const hexEncoded = encodeHex("some text to encode"); +console.log(hexEncoded); // "736f6d65207465787420746f20656e636f6465" // We can convert back to a string by using the decode method. -const hexDecoded = hex.decode(hexEncoded); -console.log(textDecoder.decode(hexDecoded)); +const hexDecoded = decodeHex(hexEncoded); +console.log(textDecoder.decode(hexDecoded)); // "some text to encode" diff --git a/data/http-server-files.ts b/data/http-server-files.ts index be3e81e..ea54e5b 100644 --- a/data/http-server-files.ts +++ b/data/http-server-files.ts @@ -4,14 +4,15 @@ * @tags cli, deploy * @run --allow-net --allow-read * @resource {https://deno.land/api?s=Deno.serve} Doc: Deno.serve - * @resource {$std/http/file_server.ts} Doc: std/http/file_server + * @resource {https://jsr.io/@std/http/doc/file_server/~} Doc: @std/http/file_server * @resource {/http-server} Example: HTTP Server: Hello World + * @dependency jsr:@std/http * * An example of a HTTP server that serves files. */ // Import utility methods for serving files with mime types. -import { serveDir, serveFile } from "$std/http/file_server.ts"; +import { serveDir, serveFile } from "@std/http/file_server"; // Here we start a simple server Deno.serve((req: Request) => { diff --git a/data/import-export.ts b/data/import-export.ts index 4d1913e..6f17899 100644 --- a/data/import-export.ts +++ b/data/import-export.ts @@ -34,7 +34,10 @@ sayHello("World"); import * as util from "./util.ts"; util.sayHello("World"); -// Imports don't have to be relative, they can also reference absolute file or -// https URLs. +// Imports don't have to be relative, they can also reference absolute files, +// https URLs, or JSR packages. import { VERSION } from "https://deno.land/std/version.ts"; console.log(VERSION); + +// deno-lint-ignore no-unused-vars +import { parse } from "jsr:@std/yaml"; diff --git a/data/importing-json.ts b/data/importing-json.ts index 278eff3..9bf5040 100644 --- a/data/importing-json.ts +++ b/data/importing-json.ts @@ -11,7 +11,7 @@ // File: ./main.ts // JSON files can be imported in JS and TS modules. When doing so, you need to -// specify the "json" import assertion type. +// specify the type: "json" import attribute. import file from "./version.json" with { type: "json" }; console.log(file.version); diff --git a/data/mongo.ts b/data/mongo.ts index 9ef9cfb..5d341b7 100644 --- a/data/mongo.ts +++ b/data/mongo.ts @@ -3,13 +3,14 @@ * @difficulty intermediate * @tags cli, deploy * @run --allow-net --allow-sys --allow-read - * @resource {https://deno.land/x/mongo} Deno MongoDB on deno.land/x + * @resource {https://www.npmjs.com/package/mongodb} MongoDB on npmjs.com + * @dependency npm:mongodb * - * Using the Deno MongoDB client, you can connect to a Mongo database + * Using the official MongoDB client, you can connect to a Mongo database * running anywhere. */ -import { MongoClient } from "npm:mongodb@6.1.0"; +import { MongoClient } from "mongodb"; // Create a new instance of the MongoDB client running locally on port 27017 const client = new MongoClient("mongodb://127.0.0.1:27017"); diff --git a/data/npm.ts b/data/npm.ts index feef881..ccb2b4f 100644 --- a/data/npm.ts +++ b/data/npm.ts @@ -5,24 +5,27 @@ * @run --allow-net --allow-read --allow-env * @resource {https://docs.deno.com/runtime/manual/node} Node.js / npm support in Deno * @resource {https://docs.deno.com/runtime/manual/node/npm_specifiers} npm: specifiers - * @resource {https://www.npmjs.com/package/express} express module on npm + * @resource {https://www.npmjs.com/package/express} express on npmjs.com + * @dependency npm:express + * @dependency npm:@types/express * * Use JavaScript modules from npm in your Deno programs with the "npm:" * specifier in your imports. */ -// Import the express module from npm using an npm: prefix, and appending a -// version number. Dependencies from npm can be configured in an import map -// also. -import express from "npm:express@4.18.2"; +// After adding the module using deno add, you can import it like any other +// module. -// Create an express server +// @deno-types="@types/express"; +import express from "express"; + +// Create an express server. const app = express(); -// Configure a route that will process HTTP GET requests +// Configure a route that will process HTTP GET requests. app.get("/", (_req, res) => { res.send("Welcome to the Dinosaur API!"); }); -// Start an HTTP server using the configured Express app +// Start an HTTP server using the configured Express app. app.listen(3000); diff --git a/data/parsing-serializing-csv.ts b/data/parsing-serializing-csv.ts index 1a86582..c6e3336 100644 --- a/data/parsing-serializing-csv.ts +++ b/data/parsing-serializing-csv.ts @@ -5,10 +5,12 @@ * @run * @resource {/import-export} Example: Importing & Exporting * @resource {https://datatracker.ietf.org/doc/html/rfc4180} Spec: CSV + * @resource {https://jsr.io/@std/csv} Doc: @std/csv + * @dependency jsr:@std/csv * * CSV is a data serialization format that is designed to be portable for table-like applications. */ -import { parse, stringify } from "$std/csv/mod.ts"; +import { parse, stringify } from "@std/csv"; // To parse a CSV string, you can use the the standard library's CSV // parse function. The value is returned as a JavaScript object. diff --git a/data/parsing-serializing-toml.ts b/data/parsing-serializing-toml.ts index e49d6bb..c7e5c52 100644 --- a/data/parsing-serializing-toml.ts +++ b/data/parsing-serializing-toml.ts @@ -5,10 +5,12 @@ * @run * @resource {/import-export} Example: Importing & Exporting * @resource {https://toml.io} Spec: TOML + * @resource {https://jsr.io/@std/toml} Doc: @std/toml + * @dependency jsr:@std/toml * * TOML is a widely used configuration language designed to be feature-rich and intuitive to write. */ -import { parse, stringify } from "$std/toml/mod.ts"; +import { parse, stringify } from "@std/toml"; // To parse a TOML string, you can use the the standard library's TOML // parse function. The value is returned as a JavaScript object. diff --git a/data/parsing-serializing-yaml.ts b/data/parsing-serializing-yaml.ts index 7c9fa6b..745a37b 100644 --- a/data/parsing-serializing-yaml.ts +++ b/data/parsing-serializing-yaml.ts @@ -5,10 +5,12 @@ * @run * @resource {/import-export} Example: Importing & Exporting * @resource {https://yaml.org} Spec: YAML + * @resource {https://jsr.io/@std/yaml} Doc: @std/yaml + * @dependency jsr:@std/yaml * * YAML is a widely used data serialization language designed to be easily human readable and writeable. */ -import { parse, stringify } from "$std/yaml/mod.ts"; +import { parse, stringify } from "@std/yaml"; // To parse a YAML string, you can use the the standard library's YAML // parse function. The value is returned as a JavaScript object. diff --git a/data/path-operations.ts b/data/path-operations.ts index dc0c951..c389462 100644 --- a/data/path-operations.ts +++ b/data/path-operations.ts @@ -3,15 +3,16 @@ * @difficulty beginner * @tags cli * @run --allow-read - * @resource {$std/path} Deno: std/path + * @resource {https://jsr.io/@std/path} Doc: @std/path * @resource {https://deno.land/api?s=Deno.cwd} Deno: Deno.cwd + * @dependency jsr:@std/path * * Many applications need to manipulate file paths in one way or another. * The Deno standard library provides simple utilities for this. */ // First we will import the module from the Deno standard library -import * as path from "$std/path/mod.ts"; +import * as path from "@std/path"; // Converting from a file url to a directory can be done simply by the `fromFileUrl` // method from the appropriate implementation. diff --git a/data/redis.ts b/data/redis.ts index 5efe8fa..94a7554 100644 --- a/data/redis.ts +++ b/data/redis.ts @@ -3,30 +3,32 @@ * @difficulty intermediate * @tags cli, deploy * @run --allow-net --allow-env - * @resource {https://deno.land/x/r2d2} r2d2 on deno.land/x + * @resource {https://jsr.io/@iuioiua/r2d2} r2d2 module on jsr.io * @resource {https://redis.io/docs/getting-started/} Getting started with Redis + * @dependency jsr:@iuioiua/r2d2 * * Using the r2d2 module, you can connect to a Redis database running anywhere. */ // Import the `sendCommand()` function from r2d2 -import { sendCommand } from "https://deno.land/x/r2d2/mod.ts"; +import { RedisClient } from "@iuioiua/r2d2"; // Create a TCP connection with the Redis server const redisConn = await Deno.connect({ port: 6379 }); +const redisClient = new RedisClient(redisConn); // Authenticate with the server by sending the command "AUTH " -await sendCommand(redisConn, [ +await redisClient.sendCommand([ "AUTH", Deno.env.get("REDIS_USERNAME")!, Deno.env.get("REDIS_PASSWORD")!, ]); // Set the "hello" key to have value "world" using the command "SET hello world" -await sendCommand(redisConn, ["SET", "hello", "world"]); // "OK" +await redisClient.sendCommand(["SET", "hello", "world"]); // "OK" // Get the "hello" key using the command "GET hello" -await sendCommand(redisConn, ["GET", "hello"]); // "world" +await redisClient.sendCommand(["GET", "hello"]); // "world" // Close the connection to the database redisConn.close(); diff --git a/data/typescript.ts b/data/typescript.ts index d5577f4..b99ef1e 100644 --- a/data/typescript.ts +++ b/data/typescript.ts @@ -10,13 +10,13 @@ * fine. */ -// Define an interface in TypeScript +// Define an interface in TypeScript. interface Person { name: string; age: number; } -// Provide a typed input to a function +// Provide a typed input to a function. function greet(person: Person) { return "Hello, " + person.name + "!"; } diff --git a/data/ulid.ts b/data/ulid.ts index cab033a..c27e5ea 100644 --- a/data/ulid.ts +++ b/data/ulid.ts @@ -4,6 +4,8 @@ * @tags cli, deploy * @run * @resource {https://github.com/ulid/spec} ULID: Specification + * @resource {https://jsr.io/@std/ulid} Doc: @std/ulid + * @dependency jsr:@std/ulid * * One common need for distributed systems are identifiers. ULIDs are a universally * unique lexicographically sortable identifier with some nice properties. They are @@ -12,7 +14,7 @@ */ // The standard library contains a function for generating ULIDs. -import { ulid } from "$std/ulid/mod.ts"; +import { ulid } from "@std/ulid"; // To generate a ULID, simply call the function. console.log(ulid()); diff --git a/data/uuids.ts b/data/uuids.ts index 4ee10d2..db78522 100644 --- a/data/uuids.ts +++ b/data/uuids.ts @@ -4,7 +4,8 @@ * @tags cli, deploy, web * @run * @resource {https://developer.mozilla.org/en-US/docs/Web/API/Crypto/randomUUID} MDN: crypto.randomUUID - * @resource {$std/uuid/mod.ts} Doc: std/uuid + * @resource {https://jsr.io/@std/uuid} Doc: @std/uuid + * @dependency jsr:@std/uuid * * UUIDs (universally unique identifier) can be used to uniquely identify some * object or data. @@ -16,7 +17,7 @@ const myUUID = crypto.randomUUID(); console.log("Random UUID:", myUUID); // The standard library contains some more functions for working with UUIDs. -import * as uuid from "$std/uuid/mod.ts"; +import * as uuid from "@std/uuid"; // You can validate that a given string is a valid UUID. console.log(uuid.validate("not a UUID")); // false diff --git a/data/walking-directories.ts b/data/walking-directories.ts index c1bf93a..6a9ddfb 100644 --- a/data/walking-directories.ts +++ b/data/walking-directories.ts @@ -4,7 +4,8 @@ * @tags cli * @run --allow-read * @resource {https://deno.land/api?s=Deno.readDir} Doc: Deno.readDir - * @resource {$std/fs/walk.ts} Doc: std/walk + * @resource {https://jsr.io/@std/fs} Doc: @std/fs + * @dependency jsr:@std/fs * * When doing something like filesystem routing, it is * useful to be able to walk down a directory to visit @@ -20,7 +21,7 @@ for await (const dirEntry of Deno.readDir(".")) { // If on the other hand you need to recursively walk // a repository, the standard library has a method for this. // In the most simple case it is a drop-in replacement -import { walk } from "$std/fs/walk.ts"; +import { walk } from "@std/fs/walk"; for await (const dirEntry of walk(".")) { console.log("Recursive walking:", dirEntry.name); diff --git a/data/watching-files.ts b/data/watching-files.ts index c6657a0..eff3877 100644 --- a/data/watching-files.ts +++ b/data/watching-files.ts @@ -5,7 +5,7 @@ * @run --allow-read * @resource {https://deno.land/api?s=Deno.watchFs} Doc: Deno.watchFs * @resource {https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/for-await...of} MDN: for await of - * @resource {$std/async/debounce.ts} Doc: std/debounce + * @resource {https://jsr.io/@std/async} Doc: @std/debounce * * When creating frameworks or CLI tools, it is often necessary to watch the filesystem for changes. */ @@ -25,7 +25,7 @@ for await (const event of watcher) { // to every change instantly. Events will be duplicated and multiple events will // be dispatched for the same changes. To get around this, we can "debounce" our // functions. -import { debounce } from "$std/async/debounce.ts"; +import { debounce } from "@std/async/debounce"; // In this specific case, we use the standard library to do the work for us. // This function will run at most once every two hundred milliseconds diff --git a/data/writing-tests.ts b/data/writing-tests.ts index 9ae1a64..92b968d 100644 --- a/data/writing-tests.ts +++ b/data/writing-tests.ts @@ -4,7 +4,8 @@ * @tags cli * @run deno test --allow-read --allow-write * @resource {https://deno.land/api?s=Deno.test} Doc: Deno.test - * @resource {$std/testing/asserts.ts} Doc: std/testing/asserts + * @resource {https://jsr.io/@std/assert} Doc: @std/assert + * @dependency jsr:@std/assert * * One of the most common tasks in developing software is writing tests for * existing code. Deno has a built-in test runner which makes this very easy. @@ -12,7 +13,7 @@ // First, we import assert statements from the standard library. There are // quite a few options but we will just import the most common ones here. -import { assert, assertEquals } from "$std/assert/mod.ts"; +import { assert, assertEquals } from "@std/assert"; // The most simple way to use the test runner is to just pass it a description // and a callback function diff --git a/deno.json b/deno.json index 7366fe2..f043071 100644 --- a/deno.json +++ b/deno.json @@ -14,17 +14,34 @@ }, "imports": { "$fresh/": "https://deno.land/x/fresh@1.4.3/", - "preact": "https://esm.sh/preact@10.15.1", - "preact/": "https://esm.sh/preact@10.15.1/", - "preact-render-to-string": "https://esm.sh/*preact-render-to-string@6.2.1", - "@preact/signals": "https://esm.sh/*@preact/signals@1.1.3", - "@preact/signals-core": "https://esm.sh/*@preact/signals-core@1.2.3", - "twind": "https://esm.sh/twind@0.16.19", - "twind/": "https://esm.sh/twind@0.16.19/", "$gfm": "https://deno.land/x/gfm@0.1.28/mod.ts", "$prism": "https://esm.sh/prismjs@1.29.0", "$prism/": "https://esm.sh/prismjs@1.29.0/", - "$std/": "https://deno.land/std@0.207.0/" + "$std/": "https://deno.land/std@0.207.0/", + "@iuioiua/r2d2": "jsr:@iuioiua/r2d2@^2.1.1", + "@preact/signals": "https://esm.sh/*@preact/signals@1.1.3", + "@preact/signals-core": "https://esm.sh/*@preact/signals-core@1.2.3", + "@std/assert": "jsr:@std/assert@^0.220.1", + "@std/async": "jsr:@std/async@^0.220.1", + "@std/bytes": "jsr:@std/bytes@^0.220.1", + "@std/cli": "jsr:@std/cli@^0.220.1", + "@std/csv": "jsr:@std/csv@^0.220.1", + "@std/encoding": "jsr:@std/encoding@^0.220.1", + "@std/fs": "jsr:@std/fs@^0.220.1", + "@std/http": "jsr:@std/http@^0.220.1", + "@std/path": "jsr:@std/path@^0.220.1", + "@std/toml": "jsr:@std/toml@^0.220.1", + "@std/ulid": "jsr:@std/ulid@^0.220.1", + "@std/uuid": "jsr:@std/uuid@^0.220.1", + "@std/yaml": "jsr:@std/yaml@^0.220.1", + "@types/express": "npm:@types/express@^4.17.21", + "express": "npm:express@^4.19.2", + "mongodb": "npm:mongodb@^6.5.0", + "preact": "https://esm.sh/preact@10.15.1", + "preact-render-to-string": "https://esm.sh/*preact-render-to-string@6.2.1", + "preact/": "https://esm.sh/preact@10.15.1/", + "twind": "https://esm.sh/twind@0.16.19", + "twind/": "https://esm.sh/twind@0.16.19/" }, "lock": false, "lint": { diff --git a/islands/CopyButton.tsx b/islands/CopyButton.tsx index 38615a9..602f243 100644 --- a/islands/CopyButton.tsx +++ b/islands/CopyButton.tsx @@ -16,9 +16,13 @@ function Copy() { ); } -export default function CopyButton(props: { text: string }) { +export default function CopyButton(props: { text: string; class?: string }) { return ( -
+