dsh-mini-utility-dock 0.5.1 → 0.6.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/CHANGELOG.en.md +20 -9
- package/CHANGELOG.md +20 -9
- package/README.en.md +22 -6
- package/README.md +22 -6
- package/bin/dsh-mini-utility-dock.js +71 -26
- package/bin/dsh-plugin-docs.js +54 -20
- package/bin/dsh-plugin-parity.js +105 -60
- package/dist/guard.js +18 -21
- package/dist/host-http.js +207 -0
- package/dist/launcher.js +19 -16
- package/dist/loopback.js +11 -14
- package/package.json +7 -2
package/dist/launcher.js
CHANGED
|
@@ -1,18 +1,20 @@
|
|
|
1
|
-
//
|
|
1
|
+
// The shared launcher assembly: one icon plus the menu of panels it opens, for a
|
|
2
|
+
// plugin's browser half.
|
|
2
3
|
//
|
|
3
4
|
// This fragment has ONE source of truth: dsh-mini-utility-dock/dist/launcher.js.
|
|
4
5
|
// DSH client artifacts are self-contained classic scripts, so the fragment is
|
|
5
6
|
// embedded into lib/client.js at build time by
|
|
6
7
|
// npm run launcher:sync (write it)
|
|
7
8
|
// npm run launcher:check (fail on drift)
|
|
8
|
-
// instead of being imported: a bare import would put a runtime dependency on
|
|
9
|
-
//
|
|
9
|
+
// instead of being imported: a bare import would put a runtime dependency on
|
|
10
|
+
// this package into the bundle that embeds it, and an embedding plugin ships
|
|
10
11
|
// standalone, with nothing else required.
|
|
11
12
|
//
|
|
12
|
-
// The launcher is one icon that opens a menu of
|
|
13
|
+
// The launcher is one icon that opens a menu of utility panels. It is contributed
|
|
13
14
|
// through slots, not through a page-local protocol: exactly one copy of this
|
|
14
|
-
// assembly runs per page
|
|
15
|
-
// declares the menu seat
|
|
15
|
+
// assembly runs per page — the first to load wins the window mutex, registers the
|
|
16
|
+
// launcher, and declares the menu seat — while the other copies register nothing
|
|
17
|
+
// here and only wait to take the claim over once their owner is disposed.
|
|
16
18
|
const UTILITY_ITEM_SLOT = 'createhelper.utility.item'
|
|
17
19
|
const UTILITY_MUTEX_KEY = '__CREATEHELPER_DSH_UTILITY_LAUNCHER_V1__'
|
|
18
20
|
const UTILITY_CSS_ID = 'createhelper-utility-launcher'
|
|
@@ -21,7 +23,7 @@ const UTILITY_MEASURE_TRIES = 120
|
|
|
21
23
|
const UTILITY_ICON = '<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><rect x="3" y="3" width="7" height="7" rx="2"></rect><rect x="14" y="3" width="7" height="7" rx="2"></rect><rect x="3" y="14" width="7" height="7" rx="2"></rect><rect x="14" y="14" width="7" height="7" rx="2"></rect></svg>'
|
|
22
24
|
|
|
23
25
|
// The launcher's own chrome, injected once by whichever copy wins the mutex.
|
|
24
|
-
// The rows
|
|
26
|
+
// The rows are other plugins' components, so the menu styles its buttons by
|
|
25
27
|
// position instead of asking every contributor for a class name.
|
|
26
28
|
function ensureUtilityStyles() {
|
|
27
29
|
if (typeof document === 'undefined') return
|
|
@@ -41,8 +43,9 @@ function ensureUtilityStyles() {
|
|
|
41
43
|
document.head.appendChild(styleEl)
|
|
42
44
|
}
|
|
43
45
|
|
|
44
|
-
// The
|
|
45
|
-
//
|
|
46
|
+
// The launcher tracks the shell's sidebar column rather than a fixed offset: its
|
|
47
|
+
// left edge sits 16px right of the sidebar's edge, and 80px while the shell has
|
|
48
|
+
// not laid that column out yet.
|
|
46
49
|
const measureUtilityLeft = () => {
|
|
47
50
|
if (typeof document === 'undefined') return UTILITY_FALLBACK_LEFT_PX
|
|
48
51
|
const overlay = document.querySelector('[data-shell-overlay]')
|
|
@@ -105,7 +108,7 @@ const useUtilityMenu = () => {
|
|
|
105
108
|
// The launcher and its menu. The menu is always rendered - a declared child
|
|
106
109
|
// slot is not conditionally declared - and hidden when closed. Choosing a row
|
|
107
110
|
// closes the menu through the click that bubbles out of it, because the rows
|
|
108
|
-
//
|
|
111
|
+
// belong to other plugins, not to this block.
|
|
109
112
|
function UtilityLauncher (props) {
|
|
110
113
|
const left = useUtilityLeft()
|
|
111
114
|
const open = useUtilityMenu()
|
|
@@ -156,11 +159,11 @@ function UtilityLauncher (props) {
|
|
|
156
159
|
// into it directly throws while that declaration is still pending, and a
|
|
157
160
|
// launcher must never cost the caller the surfaces it registers afterwards.
|
|
158
161
|
//
|
|
159
|
-
// The claim lives on the page and is released with its owner.
|
|
160
|
-
//
|
|
161
|
-
// owner would dispose its registration while the claim stayed taken, and the
|
|
162
|
-
// launcher would stay missing until the page was reloaded. A released claim
|
|
163
|
-
//
|
|
162
|
+
// The claim lives on the page and is released with its owner. Any plugin that
|
|
163
|
+
// embeds this block may win the claim, so without the release a hot reload of
|
|
164
|
+
// the owner would dispose its registration while the claim stayed taken, and the
|
|
165
|
+
// launcher would stay missing until the page was reloaded. A released claim wakes
|
|
166
|
+
// the other copies on the page, which re-register immediately.
|
|
164
167
|
const utilityClaim = () => {
|
|
165
168
|
if (typeof window === 'undefined') return null
|
|
166
169
|
const existing = window[UTILITY_MUTEX_KEY]
|
|
@@ -199,7 +202,7 @@ const registerUtilityLauncher = (scope) => {
|
|
|
199
202
|
} catch (error) {
|
|
200
203
|
release()
|
|
201
204
|
if (typeof console !== 'undefined' && typeof console.error === 'function') {
|
|
202
|
-
console.error('[utility-launcher] could not register the
|
|
205
|
+
console.error('[utility-launcher] could not register the launcher', error)
|
|
203
206
|
}
|
|
204
207
|
}
|
|
205
208
|
})
|
package/dist/loopback.js
CHANGED
|
@@ -1,28 +1,25 @@
|
|
|
1
|
-
//
|
|
1
|
+
// The loopback predicates: which Host names and which peer addresses count as
|
|
2
|
+
// loopback, for a plugin's host half that binds an API to the loopback interface.
|
|
2
3
|
//
|
|
3
4
|
// This fragment has ONE source of truth: dsh-mini-utility-dock/dist/loopback.js.
|
|
4
|
-
//
|
|
5
|
-
//
|
|
5
|
+
// A host half is plain Node ESM that its package ships standalone, so the
|
|
6
|
+
// fragment is embedded into `lib/shared.js` at build time by
|
|
6
7
|
// npm run loopback:sync (write it)
|
|
7
8
|
// npm run loopback:check (fail on drift)
|
|
8
9
|
// instead of being imported: a bare `import 'dsh-mini-utility-dock/...'` would
|
|
9
|
-
// put a runtime dependency on
|
|
10
|
-
//
|
|
11
|
-
//
|
|
12
|
-
// Why it is shared at all: these predicates were copy-pasted per repo and
|
|
13
|
-
// drifted twice. The first drift rejected IPv6 loopback everywhere; the second
|
|
14
|
-
// is that consumers disagreed on which Host spellings count as loopback
|
|
15
|
-
// (see the parity bin this package ships, which compares this block across repositories).
|
|
10
|
+
// put a runtime dependency on this package into the file that embeds it, and an
|
|
11
|
+
// embedding plugin ships standalone, with nothing else required.
|
|
16
12
|
//
|
|
17
13
|
// "Loopback" is decided in exactly one place — LOOPBACK_HOSTNAMES plus the
|
|
18
14
|
// IPv4-mapped IPv6 form of each entry — and both the name and the address
|
|
19
|
-
// predicate route through it, so the Host path and the peer path cannot
|
|
20
|
-
//
|
|
15
|
+
// predicate route through it, so the Host path and the peer path cannot
|
|
16
|
+
// disagree. Every spelling this file accepts is a documented one; anything
|
|
17
|
+
// unrecognised fails closed.
|
|
21
18
|
//
|
|
22
19
|
// Kept a separate fragment from the host guard on purpose: the predicates are
|
|
23
20
|
// stable facts about what an address is, while the guard is a policy about who
|
|
24
|
-
// may call an API.
|
|
25
|
-
// this block and never the other way round.
|
|
21
|
+
// may call an API. The guard block reads the names this block declares, so it
|
|
22
|
+
// depends on this block and never the other way round.
|
|
26
23
|
|
|
27
24
|
// Hostnames a request to a loopback-bound API may legitimately arrive with.
|
|
28
25
|
// Exact spellings only: `api.localhost` and `127.0.0.1.evil.example` must stay
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "dsh-mini-utility-dock",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"description": "The DSH plugin family's shared assets: source fragments (the loopback predicates
|
|
3
|
+
"version": "0.6.0",
|
|
4
|
+
"description": "The DSH plugin family's shared assets: source fragments (the loopback predicates, host request guard and host HTTP glue for host halves, the utility launcher for client halves), the embedding CLI, and the family diagnostics — cross-repo drift check and bilingual docs structure check.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
7
7
|
"dsh-mini-utility-dock": "bin/dsh-mini-utility-dock.js",
|
|
@@ -29,6 +29,11 @@
|
|
|
29
29
|
"type": "git",
|
|
30
30
|
"url": "git+https://github.com/xswt442-cmd/dsh-mini-utility-dock.git"
|
|
31
31
|
},
|
|
32
|
+
"homepage": "https://github.com/xswt442-cmd/dsh-mini-utility-dock#readme",
|
|
33
|
+
"bugs": {
|
|
34
|
+
"url": "https://github.com/xswt442-cmd/dsh-mini-utility-dock/issues"
|
|
35
|
+
},
|
|
36
|
+
"author": "xswt442-cmd",
|
|
32
37
|
"keywords": [
|
|
33
38
|
"dsh",
|
|
34
39
|
"deepseek-harness",
|