@toghen/figma 0.0.0-stage → 0.1.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/LICENSE +21 -0
- package/README.md +18 -2
- package/cli/bin.mjs +19 -0
- package/cli/bridge.ts +243 -0
- package/cli/check.ts +62 -0
- package/cli/figcraft.ts +764 -0
- package/cli/figcraftApply.ts +1067 -0
- package/cli/figcraftFile.ts +476 -0
- package/cli/figcraftLibrary.ts +147 -0
- package/cli/figcraftRecord.ts +121 -0
- package/cli/figcraftScene.ts +661 -0
- package/cli/main.ts +218 -0
- package/cli/members.ts +65 -0
- package/cli/run.ts +756 -0
- package/component-files.md +665 -0
- package/dist/code.js +24161 -0
- package/dist/manifest.json +23 -0
- package/dist/ui.html +6918 -0
- package/guide.md +985 -0
- package/main/code.ts +50 -0
- package/main/components/apply.ts +704 -0
- package/main/components/endOfRun.ts +168 -0
- package/main/components/errors.ts +17 -0
- package/main/components/fieldWriter.ts +497 -0
- package/main/components/file.ts +263 -0
- package/main/components/receipt.ts +228 -0
- package/main/components/resolve.ts +1193 -0
- package/main/components/run.ts +273 -0
- package/main/components/snapshot.ts +341 -0
- package/main/components/stamp.ts +312 -0
- package/main/components/update.ts +465 -0
- package/main/dispatcher.ts +33 -0
- package/main/engines/batchRunner.ts +200 -0
- package/main/engines/ioAdapter.ts +132 -0
- package/main/engines/operationExecutor.ts +512 -0
- package/main/engines/propertyMapper.ts +221 -0
- package/main/engines/queryEngine.ts +45 -0
- package/main/engines/styleSyncEngine.ts +444 -0
- package/main/engines/variableSyncEngine.ts +561 -0
- package/main/handlers/auditSelection.ts +60 -0
- package/main/handlers/boundLayers.ts +51 -0
- package/main/handlers/cancelOperation.ts +18 -0
- package/main/handlers/executeApplyBindings.ts +69 -0
- package/main/handlers/executeScaffold.ts +59 -0
- package/main/handlers/executeStyleSync.ts +121 -0
- package/main/handlers/executeVariableSync.ts +82 -0
- package/main/handlers/exportDocument.ts +114 -0
- package/main/handlers/getSelection.ts +43 -0
- package/main/handlers/index.ts +30 -0
- package/main/handlers/inspectCorrespondence.ts +172 -0
- package/main/handlers/loadConventions.ts +86 -0
- package/main/handlers/loadDocument.ts +253 -0
- package/main/handlers/lock.ts +270 -0
- package/main/handlers/planApply.ts +157 -0
- package/main/handlers/planApplyBindings.ts +79 -0
- package/main/handlers/planScaffold.ts +84 -0
- package/main/handlers/planStyleSync.ts +49 -0
- package/main/handlers/planVariableSync.ts +49 -0
- package/main/handlers/readSelectionBindings.ts +160 -0
- package/main/handlers/resizeUi.ts +105 -0
- package/main/handlers/runComponent.ts +65 -0
- package/main/handlers/templates.ts +462 -0
- package/main/handlers/tokenGraph.ts +122 -0
- package/main/runtimeState.ts +66 -0
- package/main/utils/abortController.ts +11 -0
- package/main/utils/boundVariables.ts +84 -0
- package/main/utils/buildPayloads.ts +85 -0
- package/main/utils/correspondence.ts +658 -0
- package/main/utils/designSource.ts +122 -0
- package/main/utils/figmaCollectionIndex.ts +120 -0
- package/main/utils/figmaStyleAdapter.ts +268 -0
- package/main/utils/figmaTokenAdapter.ts +255 -0
- package/main/utils/flattenDesignSystem.ts +38 -0
- package/main/utils/folds.ts +203 -0
- package/main/utils/fontStack.ts +57 -0
- package/main/utils/lists.ts +4 -0
- package/main/utils/lockStore.ts +72 -0
- package/main/utils/moves.ts +67 -0
- package/main/utils/pageRoots.ts +58 -0
- package/main/utils/planSymbols.ts +96 -0
- package/main/utils/purpose.ts +351 -0
- package/main/utils/recentStore.ts +166 -0
- package/main/utils/resolverModes.ts +271 -0
- package/main/utils/rootRecord.ts +137 -0
- package/main/utils/shardedData.ts +142 -0
- package/main/utils/standing.ts +106 -0
- package/main/utils/styleTarget.ts +51 -0
- package/main/utils/sum.ts +612 -0
- package/main/utils/symbolicIdRegistry.ts +26 -0
- package/main/utils/syncState.ts +133 -0
- package/main/utils/templateStore.ts +73 -0
- package/main/utils/tokenPath.ts +28 -0
- package/main/utils/tokenStamps.ts +91 -0
- package/manifest.json +15 -0
- package/package.json +64 -4
- package/reference.md +1609 -0
- package/shared/components/artboard.ts +126 -0
- package/shared/components/axes.ts +420 -0
- package/shared/components/bindings.ts +64 -0
- package/shared/components/blueprint.ts +248 -0
- package/shared/components/check.ts +705 -0
- package/shared/components/diff.ts +668 -0
- package/shared/components/fields.ts +404 -0
- package/shared/components/groups.ts +306 -0
- package/shared/components/index.ts +140 -0
- package/shared/components/members.ts +280 -0
- package/shared/components/model.ts +273 -0
- package/shared/components/order.ts +53 -0
- package/shared/components/read.ts +480 -0
- package/shared/components/stack.ts +124 -0
- package/shared/components/steps.ts +186 -0
- package/shared/components/validate.ts +565 -0
- package/shared/conventions.ts +28 -0
- package/shared/inputs.ts +40 -0
- package/shared/operations.ts +233 -0
- package/shared/pendingNames.ts +39 -0
- package/shared/protocol.ts +588 -0
- package/shared/tokenTypeMap.ts +21 -0
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The FigCraft target's stamps: one record on a page, keyed by object id.
|
|
3
|
+
*
|
|
4
|
+
* In FigCraft only layers and pages hold data, not variables or styles, so the stamps Figma keeps on each variable and
|
|
5
|
+
* style live together on a page (decisions, *Ruled: the stamp, one receipt per object, for every target*). Each entry
|
|
6
|
+
* is the stamp `setStamp` writes, in the same shape, so the plans read it through the same `getStamp` they use in
|
|
7
|
+
* Figma: each listed variable and style is given the shared data calls, answered from the record (`attach`).
|
|
8
|
+
*
|
|
9
|
+
* FigCraft gives a new object the highest id in use plus one, so deleting the newest variable and making another
|
|
10
|
+
* hands the old id over (measured, decisions, *What the build found: stamps in FigCraft*). Each entry therefore notes
|
|
11
|
+
* what it was written on, and an entry whose object is gone or is now of another kind is dropped (`guard`).
|
|
12
|
+
*
|
|
13
|
+
* Nothing here talks to FigCraft; `figcraft.ts` reads the record at the start of a run and writes it at the end.
|
|
14
|
+
*/
|
|
15
|
+
|
|
16
|
+
import { NAMESPACE, STAMP_KEY } from '../main/components/stamp.js';
|
|
17
|
+
|
|
18
|
+
/** The key the record is kept under, in the data of the page that holds it. The page is found by this key, not its name. */
|
|
19
|
+
export const RECORD_KEY = 'toghen';
|
|
20
|
+
|
|
21
|
+
/** The page a first write makes, when no page holds the record: a name starting with `-` makes it a divider. */
|
|
22
|
+
export const RECORD_PAGE = '-toghen';
|
|
23
|
+
|
|
24
|
+
/** One object's entry: what it was when its stamp was written, and the stamp, as `setStamp` wrote it. */
|
|
25
|
+
interface Entry {
|
|
26
|
+
of: string;
|
|
27
|
+
stamp: unknown;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
/** The stamps of a FigCraft file, by object id. */
|
|
31
|
+
export type StampRecord = Map<string, Entry>;
|
|
32
|
+
|
|
33
|
+
/** A variable or a style as the FigCraft view lists it: enough to say what it is. */
|
|
34
|
+
type Listed = { readonly id: string; readonly type?: string; readonly resolvedType?: string; readonly variableCollectionId?: string };
|
|
35
|
+
|
|
36
|
+
/** What an object is, for the guard: a variable's type and collection, a style's type. A rename keeps it. */
|
|
37
|
+
const kindOf = (object: Listed): string =>
|
|
38
|
+
object.variableCollectionId !== undefined ? `variable ${object.resolvedType} ${object.variableCollectionId}` : `style ${object.type}`;
|
|
39
|
+
|
|
40
|
+
/** The record as the page holds it, or an empty one when the page holds none, or holds text this code cannot read. */
|
|
41
|
+
export function readRecord(text: string | undefined): StampRecord {
|
|
42
|
+
const record: StampRecord = new Map();
|
|
43
|
+
if (!text) return record;
|
|
44
|
+
try {
|
|
45
|
+
const stamps = (JSON.parse(text) as { stamps?: unknown }).stamps;
|
|
46
|
+
if (typeof stamps !== 'object' || stamps === null) return record;
|
|
47
|
+
for (const [id, entry] of Object.entries(stamps)) {
|
|
48
|
+
if (typeof entry?.of === 'string' && entry.stamp !== undefined) record.set(id, { of: entry.of, stamp: entry.stamp });
|
|
49
|
+
}
|
|
50
|
+
} catch (_unreadable) {
|
|
51
|
+
// A record someone edited by hand is not ours to interpret: every object reads as unstamped, as on a first run.
|
|
52
|
+
}
|
|
53
|
+
return record;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
/**
|
|
57
|
+
* What the record keeps beside the stamps. FigCraft's document root holds no data, so the root's shared plugin data
|
|
58
|
+
* (the lock, under `toghen/lock`) is kept here, by `<namespace>/<key>`; and so is what each library copy in the file
|
|
59
|
+
* was imported from (`copies`: a copy's id → its key, `<library id>:<asset id>`), which FigCraft gives no read for.
|
|
60
|
+
*/
|
|
61
|
+
export interface Extras {
|
|
62
|
+
root: Map<string, string>;
|
|
63
|
+
copies: Map<string, string>;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
const strings = (value: unknown): Map<string, string> =>
|
|
67
|
+
new Map(
|
|
68
|
+
typeof value === 'object' && value !== null
|
|
69
|
+
? Object.entries(value).filter((entry): entry is [string, string] => typeof entry[1] === 'string')
|
|
70
|
+
: [],
|
|
71
|
+
);
|
|
72
|
+
|
|
73
|
+
/** What the record keeps beside the stamps; an old record, or one this code cannot read, keeps nothing. */
|
|
74
|
+
export function readExtras(text: string | undefined): Extras {
|
|
75
|
+
try {
|
|
76
|
+
const parsed = text ? (JSON.parse(text) as { root?: unknown; copies?: unknown }) : {};
|
|
77
|
+
return { root: strings(parsed.root), copies: strings(parsed.copies) };
|
|
78
|
+
} catch (_unreadable) {
|
|
79
|
+
return { root: new Map(), copies: new Map() };
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
/** The record as the page keeps it. */
|
|
84
|
+
export const recordText = (record: StampRecord, extras?: Extras): string =>
|
|
85
|
+
JSON.stringify({
|
|
86
|
+
stamps: Object.fromEntries(record),
|
|
87
|
+
...(extras && extras.root.size > 0 ? { root: Object.fromEntries(extras.root) } : {}),
|
|
88
|
+
...(extras && extras.copies.size > 0 ? { copies: Object.fromEntries(extras.copies) } : {}),
|
|
89
|
+
});
|
|
90
|
+
|
|
91
|
+
/** Drops each entry whose object is gone, or is now another kind of object or in another collection: an id FigCraft gave again. */
|
|
92
|
+
export function guard(record: StampRecord, objects: readonly Listed[]): void {
|
|
93
|
+
const listed = new Map(objects.map((object) => [object.id, object]));
|
|
94
|
+
for (const [id, entry] of record) {
|
|
95
|
+
const object = listed.get(id);
|
|
96
|
+
if (!object || kindOf(object) !== entry.of) record.delete(id);
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
/**
|
|
101
|
+
* Gives each object the shared data calls `getStamp` and `setStamp` make, answered from `record`. A write calls
|
|
102
|
+
* `changed`, so the record is written back only when a run wrote a stamp.
|
|
103
|
+
*/
|
|
104
|
+
export function attach(objects: readonly Listed[], record: StampRecord, changed: () => void): void {
|
|
105
|
+
const owns = (namespace: string, key: string) => namespace === NAMESPACE && key === STAMP_KEY;
|
|
106
|
+
for (const object of objects) {
|
|
107
|
+
Object.assign(object, {
|
|
108
|
+
getSharedPluginData: (namespace: string, key: string): string => {
|
|
109
|
+
const entry = owns(namespace, key) ? record.get(object.id) : undefined;
|
|
110
|
+
return entry ? JSON.stringify(entry.stamp) : '';
|
|
111
|
+
},
|
|
112
|
+
setSharedPluginData: (namespace: string, key: string, value: string): void => {
|
|
113
|
+
if (!owns(namespace, key)) throw new Error(`FigCraft keeps no data under ${namespace}/${key} on a variable or a style.`);
|
|
114
|
+
if (value === '') record.delete(object.id);
|
|
115
|
+
else record.set(object.id, { of: kindOf(object), stamp: JSON.parse(value) });
|
|
116
|
+
changed();
|
|
117
|
+
},
|
|
118
|
+
getSharedPluginDataKeys: (namespace: string): string[] => (namespace === NAMESPACE && record.has(object.id) ? [STAMP_KEY] : []),
|
|
119
|
+
});
|
|
120
|
+
}
|
|
121
|
+
}
|