@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.
- package/README.md +31 -23
- package/index.d.ts +92 -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
|
-
|
|
19
|
-
loader
|
|
20
|
-
|
|
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
|
|
25
|
-
|
|
26
|
-
plugin
|
|
27
|
-
|
|
28
|
-
|
|
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
|
-
|
|
31
|
-
|
|
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
|
-
|
|
36
|
-
|
|
37
|
-
|
|
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
|
-
|
|
41
|
-
|
|
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
|
-
|
|
53
|
+
```sh
|
|
54
|
+
npm i -D github:scm-js/plugin-api#v1.64.0
|
|
55
|
+
```
|
|
45
56
|
|
|
46
|
-
|
|
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:
|
|
2995
|
-
* history stacks
|
|
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
|
|
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
|