swatch-token 0.0.0-stage → 0.1.0

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.
@@ -0,0 +1,16 @@
1
+ import { type Change, type Edit } from "./stylesheet.js";
2
+ export declare function readSheet(file: string): {
3
+ tokens: Map<string, {
4
+ light?: string;
5
+ dark?: string;
6
+ }>;
7
+ dark: import("./stylesheet.ts").DarkSelector | null;
8
+ };
9
+ /** The whole batch on one read and one write, so a save of forty values is
10
+ * one change to the file and one hot reload. A failed check writes
11
+ * nothing. */
12
+ export declare function write(file: string, edits: Edit[]): Change[];
13
+ /** Several files' batches as one save: every file's new text is worked out
14
+ * before any is written, and if a write fails part-way the files already
15
+ * written are put back as they were. Either all of them change or none. */
16
+ export declare function writeAll(batches: Map<string, Edit[]>): Change[];
@@ -0,0 +1,13 @@
1
+ import type { IncomingMessage } from "node:http";
2
+ export type Trust = {
3
+ /** Vite's `server.allowedHosts`: true for any host, or a list (a leading "." allows subdomains) */
4
+ allowedHosts?: true | string[];
5
+ /** origins named in Swatch's options, e.g. "https://my-tunnel.example" */
6
+ allowedOrigins?: string[];
7
+ };
8
+ /** Why a write is refused, or null when it may go ahead. */
9
+ export declare function refuseWrite(req: Pick<IncomingMessage, "headers"> & {
10
+ socket: {
11
+ remoteAddress?: string;
12
+ };
13
+ }, trust?: Trust): string | null;
@@ -0,0 +1,71 @@
1
+ import { THEMES, type Change, type DarkSelector, type Edit, type Theme } from "./stylesheet.js";
2
+ export type Options = {
3
+ /** The stylesheet(s) the tokens live in, from the project root. Left
4
+ * out, every stylesheet in the project that declares custom properties
5
+ * on a theme is used. */
6
+ css?: string | string[];
7
+ /** Where uses are counted, from the project root. Default: the whole
8
+ * project, without the folders below. */
9
+ src?: string;
10
+ /** Section titles for the panel, each with a pattern its token names
11
+ * match, tried in order. Left out, tokens are grouped by the first
12
+ * word of their name. */
13
+ groups?: Record<string, RegExp | string>;
14
+ /** Show "Save & send to agent" and "Figma sync", which leave requests in
15
+ * `.swatch/requests.jsonl` for a coding agent to pick up. */
16
+ agent?: boolean;
17
+ /** Folders, from the project root, that are neither searched for
18
+ * stylesheets nor counted for uses (node_modules, hidden folders and the
19
+ * build output are left out already). */
20
+ ignore?: string[];
21
+ /** Origins besides the dev server's own that may save, e.g. a tunnel's
22
+ * "https://my-tunnel.example" (hosts in Vite's `server.allowedHosts`
23
+ * are trusted already). */
24
+ allowedOrigins?: string[];
25
+ };
26
+ export type Token = {
27
+ name: string;
28
+ light?: string;
29
+ dark?: string;
30
+ /** the stylesheet each value is in, from the project root */
31
+ file: string;
32
+ /** how its stylesheet selects the dark theme, where that differs from the project's */
33
+ darkAt?: DarkSelector;
34
+ uses: {
35
+ file: string;
36
+ n: number;
37
+ }[];
38
+ };
39
+ export type Sheet = {
40
+ files: string[];
41
+ tokens: Token[];
42
+ dark: DarkSelector | null;
43
+ groups: [string, string][] | null;
44
+ agent: boolean;
45
+ changes?: Change[];
46
+ };
47
+ export declare class Project {
48
+ readonly root: string;
49
+ readonly options: Options;
50
+ /** folders left out of every search, absolute */
51
+ private readonly skip;
52
+ private watching;
53
+ private sheets;
54
+ private sources;
55
+ constructor(root: string, options?: Options, skip?: string[]);
56
+ private get src();
57
+ watch(): void;
58
+ /** A file changed (or was added or removed: `listChanged`). */
59
+ forget(path: string, listChanged: boolean): void;
60
+ /** The stylesheets that hold tokens: the ones named, or every one in the
61
+ * project that declares a custom property on a theme. */
62
+ stylesheets(): string[];
63
+ read(): Sheet;
64
+ /** Sends each edit to the stylesheet that holds the token in that theme;
65
+ * failing that, the one that holds it in the other theme; failing that
66
+ * (a new token), the one with the most tokens. Every edit is checked,
67
+ * and every file's new text worked out, before any file is touched. */
68
+ write(edits: Edit[]): Change[];
69
+ }
70
+ export { THEMES };
71
+ export type { Change, Edit, Theme };
@@ -0,0 +1,42 @@
1
+ import { type Change, type Theme } from "./stylesheet.js";
2
+ export type Request = {
3
+ kind: "commit";
4
+ changes: Change[];
5
+ } | {
6
+ kind: "figma-sync";
7
+ figma: string;
8
+ };
9
+ export type Queued = Request & {
10
+ id: string;
11
+ at: string;
12
+ files: string[];
13
+ };
14
+ export type Proposal = Record<string, Partial<Record<Theme, string>>>;
15
+ export declare class Queue {
16
+ readonly dir: string;
17
+ readonly incoming: string;
18
+ constructor(root: string);
19
+ /** The queue holds only what was checked field by field: nothing a
20
+ * caller adds to the body, and no field of ours a caller can replace. */
21
+ add(r: Request, files: string[]): {
22
+ id: string;
23
+ };
24
+ /** What the agent left, or null (also while it is half written). */
25
+ take(): unknown;
26
+ clear(): void;
27
+ private get file();
28
+ private seen;
29
+ /** The requests no agent has dealt with yet, oldest first. A request that
30
+ * has been dealt with is taken out of the file (below), so the file only
31
+ * ever holds what is pending, and stays small. */
32
+ pending(): Queued[];
33
+ /** Takes a request out of the queue, as dealt with, and notes it (with
34
+ * its note) in done.jsonl, which keeps the last hundred. The panel may
35
+ * append a request while this rewrites the file: the file is read again
36
+ * and the rewrite retried if it grew in between, so no request is lost. */
37
+ resolve(id: string, note?: string): void;
38
+ /** Leaves values for the panel to load as unsaved edits: every one
39
+ * checked as a write would be, and the file put in place whole, so the
40
+ * panel never reads half of it. Returns how many values. */
41
+ propose(edits: Proposal, note?: string): number;
42
+ }
@@ -0,0 +1,51 @@
1
+ import { type AtRule, type Declaration, type Root, type Rule } from "postcss";
2
+ export type Theme = "light" | "dark";
3
+ export declare const THEMES: Theme[];
4
+ export type Edit = {
5
+ theme: Theme;
6
+ name: string;
7
+ value: string;
8
+ };
9
+ export type Change = {
10
+ name: string;
11
+ theme: Theme;
12
+ from: string | null;
13
+ to: string | null;
14
+ };
15
+ /** A block that holds a theme's declarations: a rule, or an `@theme` block. */
16
+ type Block = Rule | AtRule;
17
+ type Found = {
18
+ decl: Declaration;
19
+ theme: Theme;
20
+ };
21
+ export type DarkSelector = {
22
+ selector: string;
23
+ media: string | null;
24
+ };
25
+ export type Parsed = {
26
+ root: Root;
27
+ decls: Found[];
28
+ blocks: Record<Theme, Block[]>;
29
+ dark: DarkSelector | null;
30
+ };
31
+ export declare function parse(css: string, from: string): Parsed;
32
+ /** A declaration's value as the panel shows it. */
33
+ export declare const shown: (d: Declaration | undefined) => string | null;
34
+ /** Every custom property of the two themes in one stylesheet. The last
35
+ * declaration in a theme is the one the cascade uses. */
36
+ export declare function readText(css: string, from?: string): {
37
+ tokens: Map<string, {
38
+ light?: string;
39
+ dark?: string;
40
+ }>;
41
+ dark: DarkSelector | null;
42
+ };
43
+ export declare function check(e: Edit): void;
44
+ /** The stylesheet with a batch of edits applied, and what each changed. A
45
+ * failed check, or a result that would not read back as a stylesheet,
46
+ * throws and gives nothing. */
47
+ export declare function writeText(css: string, edits: Edit[], from?: string): {
48
+ css: string;
49
+ changes: Change[];
50
+ };
51
+ export {};
package/dist/vite.d.ts ADDED
@@ -0,0 +1,4 @@
1
+ import type { Plugin } from "vite";
2
+ import { type Options } from "./server/project.js";
3
+ export type { Options };
4
+ export default function swatch(options?: Options): Plugin;