roundel 0.3.0 → 0.3.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -176,3 +176,18 @@ colours, [flagstaff](https://www.npmjs.com/package/flagstaff) flies it, and
176
176
  none requires the others.
177
177
 
178
178
  MIT © Ofri Peretz — see [LICENSE](./LICENSE).
179
+
180
+ ## Benchmarks
181
+
182
+ Every number here is produced by `npm run bench` and published at [/docs/benchmarks](/docs/benchmarks).
183
+
184
+ Graded by the incumbent's own test suite:
185
+
186
+ | suite | passing |
187
+ | :-- | --: |
188
+ | `chalk` | 58 / 58 |
189
+ ## Where it sits
190
+
191
+ Plugins register under the `tokens` key, against the one schema the whole family shares.
192
+
193
+ `burgee` and `flagstaff` build on it, and it builds on nothing in this family.
package/dist/chalk.js CHANGED
@@ -1,4 +1,5 @@
1
1
  import { colorLevel } from './policy.js';
2
+ import { processRuntime } from './runtime.js';
2
3
  import { sgr } from './tokens.js';
3
4
  const MODIFIERS = {
4
5
  reset: [0, 0],
@@ -120,16 +121,13 @@ function builder(root, chain, visible) {
120
121
  },
121
122
  });
122
123
  }
123
- const proc = globalThis
124
- .process;
125
- const detect = (stream) => colorLevel({ env: proc?.env ?? {}, argv: proc?.argv ?? [], isTTY: { stdout: proc?.[stream]?.isTTY === true } });
126
- const stdoutLevel = detect('stdout');
127
- const stderrLevel = detect('stderr');
124
+ const stdoutLevel = colorLevel(processRuntime());
125
+ const stderrLevel = colorLevel(processRuntime('stderr'));
128
126
  const info = (level) => (level === 0 ? false : { level, hasBasic: true, has256: level >= 2, has16m: level === 3 });
129
127
  function create(options = {}, detected = stdoutLevel) {
130
- if (options.level !== undefined)
131
- checkLevel(options.level);
132
- return builder({ level: options.level ?? detected }, [], false);
128
+ const { level = detected } = options;
129
+ checkLevel(level);
130
+ return builder({ level }, [], false);
133
131
  }
134
132
  export class Chalk {
135
133
  constructor(options) {
package/dist/policy.d.ts CHANGED
@@ -13,21 +13,7 @@
13
13
  * 9,370 bytes. Comments are stripped from `dist`, so the prose is free; the statements
14
14
  * are not.
15
15
  */
16
- /**
17
- * The slice of a runtime the policy needs. burgee's `processRuntime` satisfies it, so
18
- * does a two-line literal in a test; nothing here imports a type from anywhere.
19
- */
20
- export interface Runtime {
21
- env: Record<string, string | undefined>;
22
- isTTY: {
23
- stdout: boolean;
24
- };
25
- /**
26
- * The process arguments, when the caller owns them: `--color`, `--no-color` and
27
- * `--color=…` are read here and nowhere else. A test literal leaves it out.
28
- */
29
- argv?: readonly string[];
30
- }
16
+ import { type Runtime } from './runtime.js';
31
17
  export type OutputMode = 'tty' | 'pipe' | 'json' | 'accessible' | 'ci';
32
18
  declare const MAX_LEVEL = 3;
33
19
  /** chalk's levels: none, 16 colours, 256 colours, truecolor. */
@@ -90,4 +76,13 @@ export declare const flown: {
90
76
  level: ColorLevel;
91
77
  paint: Partial<Record<TokenName, Paint>>;
92
78
  };
93
- export {};
79
+ /**
80
+ * The slice of a runtime this file reads is declared in `./runtime.js`, beside the one
81
+ * function in the package that names the process (Y9), and re-exported here because
82
+ * `roundel/policy` is the subpath a caller imports it from. One declaration, two doors.
83
+ *
84
+ * The import at the top is type-only, so `verbatimModuleSyntax` erases it whole: `policy.js`
85
+ * reaches no new module, and the weight of every subpath that stands on it is unchanged.
86
+ * `subpath-isolation.test.ts` is what holds that.
87
+ */
88
+ export type { Runtime };
@@ -0,0 +1,41 @@
1
+ /**
2
+ * The slice of the world this package needs, and the one file in it that names the process
3
+ * (Y9). The same seam `paratext/src/runtime.ts` and `burgee/src/runtime.ts` declare, for
4
+ * the same reason: `policy.ts` answers "where is this output going?" from a `Runtime`, so a
5
+ * test declares a terminal in two lines and a host can lie about one on purpose.
6
+ *
7
+ * The guarded cast below moved here whole from `chalk.ts`, unchanged. It is guarded because
8
+ * `process` is not a given where a bundle runs, and it is bound to a local because a
9
+ * textual lock cannot tell `proc?.env` from any other local — the exemption is recorded in
10
+ * burgee's `process-reference-lock.test.ts` against this file, so a reader looking for it
11
+ * finds it, but it is the cast and not the entry that keeps roundel honest.
12
+ *
13
+ * Nothing is cached here. `./chalk` calls `processRuntime()` twice at import because
14
+ * chalk's contract is "detect the terminal at import" (R6); every other caller in the
15
+ * family passes its own `Runtime` and never reaches this file at all.
16
+ */
17
+ /**
18
+ * The slice of a runtime the policy needs. burgee's `processRuntime` satisfies it, so does
19
+ * a two-line literal in a test; nothing here imports a type from anywhere.
20
+ */
21
+ export interface Runtime {
22
+ env: Record<string, string | undefined>;
23
+ isTTY: {
24
+ stdout: boolean;
25
+ };
26
+ /**
27
+ * The process arguments, when the caller owns them: `--color`, `--no-color` and
28
+ * `--color=…` are read in `policy.ts` and nowhere else. A test literal leaves it out.
29
+ */
30
+ argv?: readonly string[];
31
+ }
32
+ /**
33
+ * The real process. `stream` names the stream this output is going to — `chalkStderr` and
34
+ * `supportsColorStderr` detect against stderr, as chalk does — and its `isTTY` lands in
35
+ * `isTTY.stdout`, which is the policy's name for "the stream this output goes to" rather
36
+ * than for fd 1 in particular.
37
+ *
38
+ * `argv` defaults to empty rather than absent: `exactOptionalPropertyTypes` makes an
39
+ * optional `argv` mean "the key may be missing", not "the value may be undefined".
40
+ */
41
+ export declare const processRuntime: (stream?: "stdout" | "stderr") => Runtime;
@@ -0,0 +1,2 @@
1
+ const proc = globalThis.process;
2
+ export const processRuntime = (stream = 'stdout') => ({ env: proc?.env ?? {}, argv: proc?.argv ?? [], isTTY: { stdout: proc?.[stream]?.isTTY === true } });
package/dist/schema.json CHANGED
@@ -1 +1 @@
1
- {"$schema":"https://json-schema.org/draft/2020-12/schema","$id":"https://github.com/ofri-peretz/burgee/blob/main/packages/flagstaff/src/schema.json","title":"flagstaff plugin","description":"A plugin is one plain object. Everything in it is data that can be read without running it; the only functions allowed are a component's `static` (required) and `frame` (optional). A spinner or component without a static projection is refused at register().","type":"object","required":["name"],"additionalProperties":true,"properties":{"name":{"type":"string","minLength":1,"description":"The plugin's name; also the prefix a host may use when two plugins contribute the same key."},"contract":{"type":"integer","minimum":1,"description":"The plugin contract this object follows. A host refuses a newer contract than it knows."},"tokens":{"type":"object","description":"A roundel theme: semantic token name to a hex colour, contrast-checked when flown.","additionalProperties":{"type":"string","pattern":"^#[0-9a-fA-F]{6}$"}},"glyphs":{"type":"object","description":"Symbols by meaning: `ok`, `fail`, `warn`, `info`, `running`. A plugin that ships glyphs changes every built-in that draws one.","additionalProperties":{"type":"string","minLength":1}},"spinners":{"type":"object","description":"Spinner styles by name, in cli-spinners' shape plus the static projection.","additionalProperties":{"$ref":"#/$defs/spinner"}},"borders":{"type":"object","description":"Border styles a box can be drawn with, by name.","additionalProperties":{"$ref":"#/$defs/border"}},"components":{"type":"object","description":"Components by name: `static(state)` returns the text a pipe, an agent or a screen reader gets; `frame(t, state)` is the optional animated form.","additionalProperties":{"$ref":"#/$defs/component"}}},"$defs":{"spinner":{"type":"object","required":["frames","interval","static"],"properties":{"frames":{"type":"array","items":{"type":"string"},"minItems":1},"interval":{"type":"integer","minimum":1,"description":"Milliseconds between frames on a terminal."},"static":{"type":"string","description":"What a pipe prints instead of the animation."}}},"component":{"type":"object","required":["static"],"properties":{"static":{"description":"(state) => string. Required: the projection every non-terminal mode prints."},"frame":{"description":"(t, state) => string. Optional: the frame at t milliseconds since hoisting."},"sample":{"type":"object","required":["running","done"],"description":"Two states to *show* this component with: `flagstaff check` and the docs gallery render `running` then `done`. Omitted, they assume `{ phase: 'running' }` and `{ phase: 'done' }` and say so in the output. The loop never reads it — a running program's state comes from the program.","properties":{"running":{"description":"The state to open with."},"done":{"description":"The state to close with."}}},"interval":{"type":"integer","minimum":1,"description":"Milliseconds between repaints when `frame` is given; 80 when omitted."}}},"border":{"type":"object","required":["topLeft","top","topRight","left","right","bottomLeft","bottom","bottomRight"],"description":"cli-boxes' shape exactly, so that corpus imports unchanged.","properties":{"topLeft":{"type":"string"},"top":{"type":"string"},"topRight":{"type":"string"},"left":{"type":"string"},"right":{"type":"string"},"bottomLeft":{"type":"string"},"bottom":{"type":"string"},"bottomRight":{"type":"string"}}}}}
1
+ {"$schema":"https://json-schema.org/draft/2020-12/schema","$id":"https://github.com/ofri-peretz/burgee/blob/main/packages/flagstaff/src/schema.json","title":"flagstaff plugin","description":"A plugin is one plain object. Everything in it is data that can be read without running it; the only functions allowed are a component's `static` (required) and `frame` (optional). A spinner or component without a static projection is refused at register().","type":"object","required":["name"],"additionalProperties":true,"properties":{"name":{"type":"string","minLength":1,"description":"The plugin's name; also the prefix a host may use when two plugins contribute the same key."},"contract":{"type":"integer","minimum":1,"description":"The plugin contract this object follows. A host refuses a newer contract than it knows."},"tokens":{"type":"object","description":"A roundel theme: semantic token name to a hex colour, contrast-checked when flown.","additionalProperties":{"type":"string","pattern":"^#[0-9a-fA-F]{6}$"},"propertyNames":{"enum":["error","warn","ok","hint","muted","command","flag","value","heading","ground"],"description":"roundel's ten semantic tokens, and nothing else — `roundel`'s own validate() refuses any other name."}},"glyphs":{"type":"object","description":"Symbols by meaning: `ok`, `fail`, `warn`, `info`, `running`. A plugin that ships glyphs changes every built-in that draws one.","additionalProperties":{"type":"string","minLength":1}},"spinners":{"type":"object","description":"Spinner styles by name, in cli-spinners' shape plus the static projection.","additionalProperties":{"$ref":"#/$defs/spinner"}},"borders":{"type":"object","description":"Border styles a box can be drawn with, by name.","additionalProperties":{"$ref":"#/$defs/border"}},"components":{"type":"object","description":"Components by name: `static(state)` returns the text a pipe, an agent or a screen reader gets; `frame(t, state)` is the optional animated form.","additionalProperties":{"$ref":"#/$defs/component"}},"capabilities":{"$ref":"#/$defs/capabilities"}},"$defs":{"spinner":{"type":"object","required":["frames","interval","static"],"properties":{"frames":{"type":"array","items":{"type":"string"},"minItems":1},"interval":{"type":"integer","minimum":1,"description":"Milliseconds between frames on a terminal."},"static":{"type":"string","description":"What a pipe prints instead of the animation."}}},"component":{"type":"object","required":["static"],"properties":{"static":{"description":"(state) => string. Required: the projection every non-terminal mode prints."},"frame":{"description":"(t, state) => string. Optional: the frame at t milliseconds since hoisting."},"sample":{"type":"object","required":["running","done"],"description":"Two states to *show* this component with: `flagstaff check` and the docs gallery render `running` then `done`. Omitted, they assume `{ phase: 'running' }` and `{ phase: 'done' }` and say so in the output. The loop never reads it — a running program's state comes from the program.","properties":{"running":{"description":"The state to open with."},"done":{"description":"The state to close with."}}},"interval":{"type":"integer","minimum":1,"description":"Milliseconds between repaints when `frame` is given; 80 when omitted."}}},"border":{"type":"object","required":["topLeft","top","topRight","left","right","bottomLeft","bottom","bottomRight"],"description":"cli-boxes' shape exactly, so that corpus imports unchanged.","properties":{"topLeft":{"type":"string"},"top":{"type":"string"},"topRight":{"type":"string"},"left":{"type":"string"},"right":{"type":"string"},"bottomLeft":{"type":"string"},"bottom":{"type":"string"},"bottomRight":{"type":"string"}}},"capability":{"type":"object","required":["name","osc","when","encode","fallback"],"additionalProperties":false,"description":"One paratext capability: what it says to the terminal, when the terminal is believed to understand it, and what prints when it does not. No functions, so it travels through JSON. `encode` and `fallback` are templates: `{field}` is the field's value, `{field|base64}` is it base64-encoded, and `[ … ]` is emitted only when every field inside it has a value.","properties":{"name":{"type":"string","minLength":1,"description":"How callers name it. Registering an existing name replaces it — how a caller corrects a guess we got wrong."},"osc":{"description":"The OSC code this speaks, or 'BEL' for the bell and for protocols that are not OSC at all, such as Kitty's.","oneOf":[{"type":"integer","minimum":0},{"const":"BEL"}]},"when":{"type":"object","description":"When the terminal is believed to understand it. Every clause must hold; `termProgram` and `envAny` are ORs within themselves. Guesses — no terminal answers 'do you do OSC 1337' — and therefore data a caller can replace.","additionalProperties":false,"properties":{"tty":{"type":"boolean","description":"Refuse a pipe. Almost always true: a file that receives OSC gets control bytes in it."},"termProgram":{"type":"array","items":{"type":"string"},"description":"Any one of these TERM_PROGRAM values."},"envAny":{"type":"array","items":{"type":"string"},"description":"Any one of these environment variables merely being set, as VTE announces itself."},"term":{"type":"string","description":"An exact TERM — Kitty is xterm-kitty."}}},"encode":{"type":"string","minLength":1,"description":"The bytes, as a template, for a terminal that does understand."},"fallback":{"type":"string","description":"What to print when it does not — PRINCIPLES rule 6. '' is a legitimate answer, a window title having nothing to say in a log; absence is not, which is why this is required and may be ''."}},"examples":[{"name":"kitty-image","osc":"BEL","when":{"tty":true,"term":"xterm-kitty"},"encode":"\u001b_Ga=T,f=100;{base64}\u001b\\","fallback":"{caption}"}]},"capabilities":{"type":"object","description":"paratext capabilities by name — the OSC section of a plugin, read the way flagstaff reads `spinners`.","additionalProperties":{"$ref":"#/$defs/capability"}},"capabilityDocument":{"description":"What paratext's `check()` accepts. Two shapes, and only one of them survives 1.0.","oneOf":[{"description":"The family shape: a plugin carrying its capabilities under `capabilities`.","type":"object","required":["name","capabilities"],"properties":{"name":{"type":"string","minLength":1},"contract":{"type":"integer","minimum":1},"capabilities":{"$ref":"#/$defs/capabilities"}}},{"deprecated":true,"description":"Deprecated: one capability as the whole document, the shape paratext's schema had before this one absorbed it. Accepted for one minor release, removed at 1.0 — `check()` validates it and says so.","$ref":"#/$defs/capability"}]}}}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "roundel",
3
- "version": "0.3.0",
3
+ "version": "0.3.1",
4
4
  "description": "The colours a CLI carries. One output policy, semantic tokens, a theme, and a chalk migration path lighter than chalk. Zero dependencies.",
5
5
  "license": "MIT",
6
6
  "type": "module",