command code

[github]

the command key in a rounded square, glinting now and then

companies 64×32 30 fps in colour or one ink 8.6 kB

use it

html

<script type="module" src="https://ascii.rest/ascii.js"></script>

<ascii-art piece="command-code" options='{"shine":5}'></ascii-art>

No install and no build step. ascii.js defines the <ascii-art> tag, loads the piece from ascii.rest, plays it while it is on screen, and holds the first frame for anyone who prefers reduced motion. Add mono, <ascii-art piece="command-code" mono>, for one ink.

react

// npm install github:bas3line/ascii
import { Ascii } from "ascii.rest/react";
import { commandCode } from "ascii.rest/pieces";

<Ascii piece={commandCode} options={{"shine":5}} />

A client component, so it works in the Next.js app router as it is. Pass the name instead, piece="command-code", to fetch the piece only when it mounts. Add mono for one ink.

astro

---
// npm install github:bas3line/ascii
import Ascii from "ascii.rest/astro";
---

<Ascii piece="command-code" options={{"shine":5}} />

Renders the first frame on the server, so the page is whole before any script runs, then plays the piece once it loads. Add mono for one ink.

typescript

// npm install github:bas3line/ascii
import { mount } from "ascii.rest";
import { commandCode } from "ascii.rest/pieces";

const el = document.querySelector<HTMLCanvasElement>("canvas")!;
const stop = mount(el, commandCode, {"shine":5});

mount plays a piece in a <pre>, or on a <canvas> for the coloured ones, and returns a function that stops it. Every piece, option and frame is typed. Mount it in a <pre> for one ink.

command-code.ts

[js] [github]
/*
 * command code: the Command Code logo, a command key cut from a rounded
 * square, with a glint crossing it every few seconds.
 *
 * Drawn from Command Code's own mark,
 * commandcode.ai/favicon/2024/safari-pinned-tab.svg: each cell holds the
 * character whose shape best matches the logo's edge through it, and 8 where
 * the logo is solid. On a canvas it is black, and a light grey on a dark page,
 * where black would sink into it; in a <pre> it is one ink, from the same
 * drawing. The logo is a trademark of its owner, shown here to name the
 * company.
 */
import type { Frame, Meta } from "../types.ts";

export interface CommandCodeOptions {
  [key: string]: unknown;
  /** Seconds between glints; 0 keeps the logo still. */
  shine: number;
}

export const meta = {
  name: "command code",
  category: "companies",
  note: "the command key in a rounded square, glinting now and then",
  cols: 64,
  rows: 32,
  fps: 30,
  options: { shine: 5 },
  // The logo's colour for a light page, then for a dark one; each as drawn, then twice lighter for the glint.
  palette: [
    "#000000", "#595959", "#b3b3b3", "#e8ebef", "#f0f2f5", "#f8f9fa",
  ],
} satisfies Meta<CommandCodeOptions>;

// In a <pre>, in the page's own colour.
const MONO = String.raw`

          __pppqq888888888888888888888888888888qqqqq__
      ._p8888888888888888888888888888888888888888888888q_
     q8888888888888888888888888888888888888888888888888888_
    p888888888888888888888888888888888888888888888888888888p
   q88888888888888888888888888888888888888888888888888888888p
  .8888888888888888888888888888888888888888888888888888888888,
  q8888888888888"'      "8888888888888P"      '"8888888888888|
  d88888888888P    .__    "8888888888"    __,    O88888888888b
  88888888888P   .p8888,   |88888888"   \8888q,   88888888888b
  88888888888b   |88888b   |88888888    888888|   d88888888888
  888888888888,   "8888P   :88888888    88888"   .888888888888
  888888888888q_                                _8888888888888
  88888888888888qq___,,,    ,,,,,,,,    .,____pp88888888888888
  8888888888888888888888   :88888888    8888888888888888888888
  8888888888888888888888   :88888888    8888888888888888888888
  8888888888888888888888   :88888888    8888888888888888888888
  8888888888888888888888   :88888888    8888888888888888888888
  88888888888888P""'                        '""888888888888888
  888888888888P'                                "8888888888888
  888888888888    qp888p   :88888888    q888q_   '888888888888
  88888888888P   |888888   |88888888.   888888|   d88888888888
  88888888888b    88888"   )88888888,   "8888P    888888888888
  d88888888888p     ''    _8888888888_    ''    .p88888888888P
  )8888888888888q_     __p888888888888q_,     _p8888888888888|
  '88888888888888888qq88888888888888888888qq88888888888888888
   )88888888888888888888888888888888888888888888888888888888P
    O888888888888888888888888888888888888888888888888888888P
     "8888888888888888888888888888888888888888888888888888"
       "88888888888888888888888888888888888888888888888P"
          '""Y88888888888888888888888888888888888PP""'

`;

// On a canvas, and the colour of each cell: an index into the logo's colours.
const ART = String.raw`

          __pppqq888888888888888888888888888888qqqqq__
      ._p8888888888888888888888888888888888888888888888q_
     q8888888888888888888888888888888888888888888888888888_
    p888888888888888888888888888888888888888888888888888888p
   q88888888888888888888888888888888888888888888888888888888p
  .8888888888888888888888888888888888888888888888888888888888,
  q8888888888888"'      "8888888888888P"      '"8888888888888|
  d88888888888P    .__    "8888888888"    __,    O88888888888b
  88888888888P   .p8888,   |88888888"   \8888q,   88888888888b
  88888888888b   |88888b   |88888888    888888|   d88888888888
  888888888888,   "8888P   :88888888    88888"   .888888888888
  888888888888q_                                _8888888888888
  88888888888888qq___,,,    ,,,,,,,,    .,____pp88888888888888
  8888888888888888888888   :88888888    8888888888888888888888
  8888888888888888888888   :88888888    8888888888888888888888
  8888888888888888888888   :88888888    8888888888888888888888
  8888888888888888888888   :88888888    8888888888888888888888
  88888888888888P""'                        '""888888888888888
  888888888888P'                                "8888888888888
  888888888888    qp888p   :88888888    q888q_   '888888888888
  88888888888P   |888888   |88888888.   888888|   d88888888888
  88888888888b    88888"   )88888888,   "8888P    888888888888
  d88888888888p     ''    _8888888888_    ''    .p88888888888P
  )8888888888888q_     __p888888888888q_,     _p8888888888888|
  '88888888888888888qq88888888888888888888qq88888888888888888
   )88888888888888888888888888888888888888888888888888888888P
    O888888888888888888888888888888888888888888888888888888P
     "8888888888888888888888888888888888888888888888888888"
       "88888888888888888888888888888888888888888888888P"
          '""Y88888888888888888888888888888888888PP""'

`;
const INK = String.raw`

          00000000000000000000000000000000000000000000
      000000000000000000000000000000000000000000000000000
     000000000000000000000000000000000000000000000000000000
    00000000000000000000000000000000000000000000000000000000
   0000000000000000000000000000000000000000000000000000000000
  000000000000000000000000000000000000000000000000000000000000
  0000000000000000      0000000000000000      0000000000000000
  0000000000000    000    000000000000    000    0000000000000
  000000000000   0000000   0000000000   0000000   000000000000
  000000000000   0000000   000000000    0000000   000000000000
  0000000000000   000000   000000000    000000   0000000000000
  00000000000000                                00000000000000
  0000000000000000000000    00000000    0000000000000000000000
  0000000000000000000000   000000000    0000000000000000000000
  0000000000000000000000   000000000    0000000000000000000000
  0000000000000000000000   000000000    0000000000000000000000
  0000000000000000000000   000000000    0000000000000000000000
  000000000000000000                        000000000000000000
  00000000000000                                00000000000000
  000000000000    000000   000000000    000000   0000000000000
  000000000000   0000000   0000000000   0000000   000000000000
  000000000000    000000   0000000000   000000    000000000000
  0000000000000     00    000000000000    00    00000000000000
  0000000000000000     000000000000000000     0000000000000000
  00000000000000000000000000000000000000000000000000000000000
   0000000000000000000000000000000000000000000000000000000000
    00000000000000000000000000000000000000000000000000000000
     000000000000000000000000000000000000000000000000000000
       00000000000000000000000000000000000000000000000000
          00000000000000000000000000000000000000000000

`;

const START = 0.5; // seconds before the first glint
const PASS = 2; // seconds a glint takes to cross
const HALF = 5; // half its width, in cells
const LEAN = 0.9; // cells it shifts left a row down, so it leans like a slash
const SOLID = "8dbqpPYOo0"; // what the glint turns to slashes; thin edges keep their shape

const lines = (art: string) => art.slice(1, -1).split("\n").map((line) => line.padEnd(meta.cols));

export default function commandCode({ shine = meta.options.shine }: Partial<CommandCodeOptions> = {}): Frame {
  const { cols, rows } = meta;
  const mono = lines(MONO), art = lines(ART), ink = lines(INK);
  const n = meta.palette.length / 6;
  const every = shine > 0 ? Math.max(shine, PASS + 0.5) : 0;
  // The glint crosses the logo's ink, edge to edge, rather than the whole frame.
  let lo = Infinity, hi = -Infinity;
  for (const pic of [mono, art])
    pic.forEach((line, y) => {
      for (let x = 0; x < cols; x++) if (line[x] !== " ") (lo = Math.min(lo, x + LEAN * y)), (hi = Math.max(hi, x + LEAN * y));
    });
  const span = hi - lo + 2 * HALF;

  return (t, { paper = false, color } = {}) => {
    const pic = color ? art : mono;
    const since = t - START;
    const at = every && since >= 0 ? lo - HALF + (span * (since % every)) / PASS : -Infinity;
    const out: string[] = [];
    for (let y = 0; y < rows; y++) {
      let line = "";
      for (let x = 0; x < cols; x++) {
        let ch = pic[y][x];
        if (ch !== " ") {
          const d = Math.abs(x + LEAN * y - at);
          let k = d < HALF ? 1 - d / HALF : 0;
          k = k * k * (3 - 2 * k);
          if (k > 0.55 && SOLID.includes(ch)) ch = "/";
          if (color) color[y * cols + x] = (paper ? 0 : 3 * n) + (k > 0.6 ? 2 : k > 0.25 ? 1 : 0) * n + parseInt(ink[y][x], 36);
        }
        line += ch;
      }
      out.push(line);
    }
    return out.join("\n");
  };
}