@scm-js/plugin-api 1.64.0 → 1.66.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.
Files changed (3) hide show
  1. package/README.md +31 -23
  2. package/index.d.ts +92 -3
  3. package/package.json +1 -1
package/README.md CHANGED
@@ -11,41 +11,49 @@ npm i -D @scm-js/plugin-api
11
11
  import type { PluginApi } from "@scm-js/plugin-api";
12
12
 
13
13
  export function activate(api: PluginApi) {
14
- api.ui.toast("Hello from a plugin.");
14
+ api.ui.toast({ title: "Hello from a plugin." });
15
15
  }
16
16
  ```
17
17
 
18
- Types only. A plugin imports them with `import type`, which is erased before the editor's
19
- loader ever sees the specifier — which is what lets this be a normal npm dependency
20
- without breaking the rule that a plugin's *runtime* code cannot import packages by name.
18
+ The package has types only. Import them with `import type`. TypeScript removes those imports
19
+ before the editor's loader sees the plugin, so it can be an ordinary npm dependency. A
20
+ plugin's run-time code cannot import packages by name, and everything it needs at run time
21
+ arrives on `api`.
22
+
23
+ ## Where to start
24
+
25
+ - [Plugins](https://docs.scmjs.dev/plugins/) is the author's guide: what a plugin can do and
26
+ how to write, load and publish one.
27
+ - The [API reference](https://docs.scmjs.dev/api/) lists every call, generated from these
28
+ declarations.
29
+ - [plugin-hello-world](https://github.com/scm-js/plugin-hello-world) is the smallest working
30
+ plugin.
21
31
 
22
32
  ## Versions
23
33
 
24
- The major **is** `PLUGIN_API_VERSION`, so `"^1"` is the range to write and it means what
25
- it says: the minor moves whenever the declarations change, and a change that would break a
26
- plugin moves the major and `PLUGIN_API_VERSION` together. The editor's own version is
27
- deliberately not in here — editor 0.1.0 to 0.2.0 is an ordinary release, and semver would
28
- read it as a break.
34
+ The package's major version is `PLUGIN_API_VERSION`, which is 1 and has never changed. Write
35
+ `"^1"` as the range. The minor version moves whenever the declarations change. A change that
36
+ would break a plugin would move the major version and `PLUGIN_API_VERSION` together.
37
+
38
+ The editor's own version is not used here. Going from editor 0.1.0 to 0.2.0 is an ordinary
39
+ release, and semver would read it as a break.
29
40
 
30
- `PLUGIN_API_VERSION` is 1 and has never moved. Your manifest's `"api": 1` is the version
31
- your plugin *needs*; an editor providing an older one refuses to load it.
41
+ Your manifest's `"api": 1` is the version your plugin needs. An editor that provides an
42
+ older one will not load it.
32
43
 
33
44
  ## This repository
34
45
 
35
- **Nothing here is written by hand** except this README and the LICENSE. `index.d.ts` and
36
- `package.json` are generated from `src/plugins/api.ts` in the editor by
37
- `npm run build:plugin-types` and published from there, so the contract has one source and
38
- one copy of its declarations. `main` is the tip; each `v*` tag is a published version.
46
+ Only this README and the LICENSE are written by hand. `index.d.ts` and `package.json` are
47
+ generated from `src/plugins/api.ts` in the editor by `npm run build:plugin-types`, and
48
+ published from there. `main` is the newest version, and each `v*` tag is a published one.
39
49
 
40
- It exists beside the registry as the audit trail behind the tarball, and as the way in for
41
- anyone whose registry the package is not on — `npm i -D github:scm-js/plugin-api#v1.0.0`
42
- works and installs exactly the same two files.
50
+ The repository is the record behind each npm release. It is also a way to install the
51
+ package without the npm registry:
43
52
 
44
- ## What the API covers
53
+ ```sh
54
+ npm i -D github:scm-js/plugin-api#v1.64.0
55
+ ```
45
56
 
46
- [`docs/plugins.md`](https://github.com/scm-js/scm-js/blob/main/docs/plugins.md) in the
47
- editor is the author's guide and the tour of what a plugin can do; this repository is only
48
- the typings for it. [`plugin-hello-world`](https://github.com/scm-js/plugin-hello-world) is
49
- the smallest working example.
57
+ That installs the same files as the registry.
50
58
 
51
59
  MIT, like the editor.
package/index.d.ts CHANGED
@@ -1155,6 +1155,13 @@ export interface SyncFieldsOp {
1155
1155
  extended: boolean;
1156
1156
  encoding: TextEncoding;
1157
1157
  };
1158
+ /**
1159
+ * For each field in `set`, `fieldHash` of the value the change was made from — what the
1160
+ * sender's dialog showed. A receiver whose copy holds something else learns that the op
1161
+ * writes over a version its sender never saw (`Applied.overwritten`). Absent from ops
1162
+ * sent by older editors, which are then never reported as overwriting.
1163
+ */
1164
+ from?: Partial<Record<SyncField, string>>;
1158
1165
  }
1159
1166
  export interface SyncExtrasOp {
1160
1167
  kind: "extras";
@@ -1241,6 +1248,34 @@ export interface HistoryEdit {
1241
1248
  * redo atoms apply it with `applyTables`.
1242
1249
  */
1243
1250
  tables?: TablesEdit;
1251
+ /**
1252
+ * A change to the whole map — Resize / Crop, Change Tileset: the map as it stands on the
1253
+ * other side of the step (`WholeState`). Undo and redo swap it with the scenario's own and
1254
+ * keep what they took out here, so the entry always holds the side it is not on. An entry
1255
+ * with this part has no other: `applyEntry` leaves it alone, and the undo and redo atoms
1256
+ * apply it with `swapWholeState`.
1257
+ */
1258
+ whole?: WholeState;
1259
+ }
1260
+ /**
1261
+ * What a whole-map change replaces: the size, the tileset and every list or grid that is
1262
+ * laid out by the map's size. Held by reference, not copied — Resize and Change Tileset
1263
+ * build new arrays rather than writing into the old ones, and every later in-place edit is
1264
+ * on the undo stack above the entry, so by the time the entry is undone the arrays it took
1265
+ * out are exactly as it left them.
1266
+ */
1267
+ export interface WholeState {
1268
+ width: number;
1269
+ height: number;
1270
+ era: number;
1271
+ tiles: Uint16Array;
1272
+ editorTiles: Uint16Array;
1273
+ isom: Uint16Array | null;
1274
+ mask: Uint8Array | null;
1275
+ units: Scenario["units"];
1276
+ sprites: Scenario["sprites"];
1277
+ doodads: Scenario["doodads"];
1278
+ locations: Scenario["locations"];
1244
1279
  }
1245
1280
  /**
1246
1281
  * Why the map changed: an edit recorded in the history, an undo or redo of one, a dialog
@@ -2292,10 +2327,14 @@ export interface Preferences {
2292
2327
  * Tools ▸ Test Map: whether to start the game after writing the map (desktop build), and
2293
2328
  * the game folder to use when the desktop build should not search ("" = search). The
2294
2329
  * browser's folder is a handle in IndexedDB (`services/handleStore.ts`), not here.
2330
+ * `target` is where Test Map, Ctrl+F5 and the toolbar send the map: `"starcraft"`, a
2331
+ * plugin's id for its `ui.testTarget`, or `""` — a plugin's target where there is one
2332
+ * (the browser at scmjs.dev), StarCraft otherwise (`services/testTargets.ts`).
2295
2333
  */
2296
2334
  testMap: {
2297
2335
  launch: boolean;
2298
2336
  dir: string;
2337
+ target: string;
2299
2338
  };
2300
2339
  /**
2301
2340
  * The desktop build's in-app updates (`editor/updates.ts`, `desktop/updater.ts`); the
@@ -2991,8 +3030,8 @@ export interface DocumentApi {
2991
3030
  launch?: boolean;
2992
3031
  }): Promise<TestMapOutcome | null>;
2993
3032
  /**
2994
- * Scenario ▸ Resize / Crop Map: a transaction outside the undo model that drops both
2995
- * history stacks (as the dialog does). Content keeps its place relative to `anchor`
3033
+ * Scenario ▸ Resize / Crop Map: one undo step, as the dialog is (on a shared map, where
3034
+ * it replaces everyone's map, both history stacks are dropped instead). Content keeps its place relative to `anchor`
2996
3035
  * (a 3 × 3 grid, row-major, 4 = centre, the default); the new ground is `terrainId`
2997
3036
  * (the tileset's default when omitted); objects outside the new bounds are dropped,
2998
3037
  * locations clamped unless `clampLocations` is false. Null with no map.
@@ -3002,7 +3041,7 @@ export interface DocumentApi {
3002
3041
  * Scenario ▸ Map Properties ▸ Tileset: change ERA and lay the terrain again with the
3003
3042
  * new tileset's terrain (tile numbers do not carry across tilesets; the doodads go with
3004
3043
  * them, everything else stays). Waits for the new graphics so the fill uses real tiles.
3005
- * Like `resize`, a transaction outside the undo model. Null with no map.
3044
+ * Like `resize`, one undo step (on a shared map, the history is dropped instead). Null with no map.
3006
3045
  */
3007
3046
  changeTileset(options: ChangeTilesetOptions): Promise<ChangeTilesetResult | null>;
3008
3047
  readonly extras: ExtrasApi;
@@ -5429,6 +5468,50 @@ export interface PreferencesPageSpec {
5429
5468
  /** Called by Reset to defaults while the page is the one showing. */
5430
5469
  reset?(): void;
5431
5470
  }
5471
+ /**
5472
+ * Another place Tools ▸ Test Map can send the map — `ui.testTarget`. The editor's own
5473
+ * target is StarCraft (the file written where the game lists it); a target of a plugin's
5474
+ * is a choice beside it on Edit ▸ Preferences ▸ Testing, a Tools menu item of its own
5475
+ * ("Test in …"), and, when the user picks it there, what Test Map, Ctrl+F5 and the
5476
+ * toolbar's Test button do.
5477
+ *
5478
+ * @example
5479
+ * api.ui.testTarget({
5480
+ * label: "This browser",
5481
+ * menuLabel: "Test in Browser",
5482
+ * description: "Plays the map in a tab of its own.",
5483
+ * run: (map) => { const tab = window.open("/play/"); void map.then((m) => m && send(tab, m)); },
5484
+ * });
5485
+ */
5486
+ export interface TestTargetSpec {
5487
+ /** What the choice is called on Preferences ▸ Testing: "This browser". Translated through the plugin's catalogue. */
5488
+ label: string;
5489
+ /** The Tools menu item that tests here whatever the choice is: "Test in Browser". */
5490
+ menuLabel: string;
5491
+ /** A line under the choice saying what happens. */
5492
+ description?: string;
5493
+ /**
5494
+ * Test the map. It is called inside the click or key press itself, before the map is
5495
+ * built, so a target that opens a window can open it at once — a browser lets a click
5496
+ * open a tab, not what follows it later. `map` resolves with the file as Save would
5497
+ * write it (build steps run, always an archive), or null when there is none; it
5498
+ * rejects when the build fails. A promise this returns that rejects is shown to the
5499
+ * user as the reason the test did not start; what it resolves with is the status-bar
5500
+ * line (nothing is shown for none).
5501
+ */
5502
+ run(map: Promise<TestMapFile | null>): void | Promise<string | void>;
5503
+ /**
5504
+ * The target's own settings, drawn under its label on Preferences ▸ Testing — the same
5505
+ * `mount` / `apply` / `reset` as `PreferencesPageSpec`.
5506
+ */
5507
+ settings?: PreferencesPageSpec;
5508
+ }
5509
+ /** The map a test target is handed. */
5510
+ export interface TestMapFile {
5511
+ bytes: Uint8Array;
5512
+ /** The file name the game would list, `.scx` or `.scm`. */
5513
+ name: string;
5514
+ }
5432
5515
  /** What a preferences page's `mount` is handed. */
5433
5516
  export interface PreferencesPageHost {
5434
5517
  readonly plugin: PluginInfo;
@@ -5723,6 +5806,12 @@ export interface UiApi {
5723
5806
  * Returns the registration; it leaves with `dispose()` or the plugin.
5724
5807
  */
5725
5808
  preferencesPage(spec: PreferencesPageSpec): Disposable;
5809
+ /**
5810
+ * A place Test Map can send the map besides StarCraft — see `TestTargetSpec`. One per
5811
+ * plugin: a second registration takes the first one's place. Returns the registration;
5812
+ * it leaves with `dispose()` or the plugin, and Test Map goes back to StarCraft.
5813
+ */
5814
+ testTarget(spec: TestTargetSpec): Disposable;
5726
5815
  /**
5727
5816
  * Take over the pointer on the map until `stop()`, Esc, a right-click, a map change
5728
5817
  * or another tool. One tool runs at a time — starting one stops the previous — and a
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@scm-js/plugin-api",
3
- "version": "1.64.0",
3
+ "version": "1.66.0",
4
4
  "description": "Type declarations for the scmJS plugin API",
5
5
  "license": "MIT",
6
6
  "types": "index.d.ts",