@linxin666/dsh-pet 0.2.0 → 0.2.2
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.i18n.yaml +2 -2
- package/README.md +15 -5
- package/README.zh.md +15 -5
- package/assets/whale/pet.json +1 -1
- package/assets/whale-refined/pet.json +7 -0
- package/assets/whale-refined/spritesheet.webp +0 -0
- package/lib/client.js +257 -53
- package/lib/client.js.map +1 -1
- package/lib/index.js +235 -83
- package/lib/invariant.js +1 -1
- package/lib/{state-Ch3f4luZ.js → state-DrMX22GL.js} +35 -5
- package/lib/types/chatter.d.ts.map +1 -1
- package/lib/types/chatter.js +167 -77
- package/lib/types/client/PetDockEntry.d.ts.map +1 -1
- package/lib/types/client/PetDockEntry.js +1 -1
- package/lib/types/client/PetSprite.d.ts.map +1 -1
- package/lib/types/client/PetSprite.js +54 -11
- package/lib/types/client/PluginSettingsCard.d.ts +22 -0
- package/lib/types/client/PluginSettingsCard.d.ts.map +1 -1
- package/lib/types/client/PluginSettingsCard.js +142 -3
- package/lib/types/client/index.d.ts.map +1 -1
- package/lib/types/client/index.js +1 -0
- package/lib/types/client/locales.d.ts +4 -0
- package/lib/types/client/locales.d.ts.map +1 -1
- package/lib/types/client/locales.js +4 -0
- package/lib/types/client/spritesheet.d.ts +1 -3
- package/lib/types/client/spritesheet.d.ts.map +1 -1
- package/lib/types/client/spritesheet.js +1 -5
- package/lib/types/loopback.d.ts +25 -0
- package/lib/types/loopback.d.ts.map +1 -0
- package/lib/types/loopback.js +68 -0
- package/lib/types/registry.d.ts +0 -2
- package/lib/types/registry.d.ts.map +1 -1
- package/lib/types/registry.js +11 -7
- package/lib/types/remarks.d.ts.map +1 -1
- package/lib/types/remarks.js +30 -0
- package/lib/types/routes.d.ts.map +1 -1
- package/lib/types/routes.js +14 -0
- package/lib/types/service.d.ts.map +1 -1
- package/package.json +1 -2
- package/src/chatter.ts +167 -77
- package/src/client/PetDockEntry.test.tsx +93 -0
- package/src/client/PetDockEntry.tsx +1 -0
- package/src/client/PetSprite.test.tsx +72 -11
- package/src/client/PetSprite.tsx +98 -30
- package/src/client/PluginSettingsCard.tsx +219 -18
- package/src/client/index.test.tsx +95 -0
- package/src/client/index.ts +1 -0
- package/src/client/locales.ts +4 -0
- package/src/client/pet-css.test.ts +15 -3
- package/src/client/pet.module.css +101 -71
- package/src/client/settings-card.module.css +90 -1
- package/src/client/spritesheet.ts +1 -6
- package/src/loopback.ts +63 -0
- package/src/registry.test.ts +49 -1
- package/src/registry.ts +11 -7
- package/src/remarks.ts +30 -0
- package/src/routes.ts +11 -0
- package/src/service.ts +0 -1
|
@@ -8,7 +8,7 @@ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
|
8
8
|
* it. Inlined into each consumer's client bundle; mirrors the official
|
|
9
9
|
* ui-plugin-config PluginCard in a self-contained slice.
|
|
10
10
|
*/
|
|
11
|
-
import { useState } from 'react';
|
|
11
|
+
import { useCallback, useEffect, useLayoutEffect, useRef, useState } from 'react';
|
|
12
12
|
import css from './settings-card.module.css';
|
|
13
13
|
/** Copy keys the card chrome itself reads; every consumer locale carries this shared vocabulary. */
|
|
14
14
|
export const CARD_COPY_KEYS = [
|
|
@@ -65,15 +65,154 @@ export function ValueField(props) {
|
|
|
65
65
|
? (_jsxs("span", { className: css.badges, children: [_jsx("span", { className: css.badge, children: props.overriddenLabel }), _jsx("button", { type: "button", className: css.reset, disabled: props.disabled, onClick: props.onReset, children: props.resetLabel })] }))
|
|
66
66
|
: null] }), _jsx("input", { id: props.id, className: props.invalid ? css.inputInvalid : css.input, type: "text", ...props.numeric === true ? { inputMode: 'numeric' } : {}, ...props.invalid ? { 'aria-invalid': true } : {}, value: props.text, placeholder: props.placeholder ?? '', disabled: props.disabled, onChange: (event) => { props.onEdit(event.target.value); } }), _jsx("p", { className: props.invalid ? css.invalid : css.hint, children: props.invalid ? props.invalidLabel : props.hint })] }));
|
|
67
67
|
}
|
|
68
|
+
const NON_SKIN_BODY_MARKERS = new Set(['dshSkinCenter', 'dshSidebarCollapsed']);
|
|
69
|
+
// 检测使用使用皮肤,用了皮肤退回原生select样式,防止样式冲突。默认外观下使用优化后的select样式。
|
|
70
|
+
function isSkinActive() {
|
|
71
|
+
const datasetList = Object.keys(document.body.dataset);
|
|
72
|
+
const isActive = datasetList.some(key => key.startsWith('dsh') && !NON_SKIN_BODY_MARKERS.has(key));
|
|
73
|
+
return isActive;
|
|
74
|
+
}
|
|
75
|
+
const SELECT_CLOSE_MS = 100;
|
|
76
|
+
/**
|
|
77
|
+
* The shared dual-mode select control. While an appearance skin is active it
|
|
78
|
+
* renders the legacy native `<select>` untouched, so element-level skin
|
|
79
|
+
* selectors keep working; under the default appearance it renders a
|
|
80
|
+
* self-drawn `role="listbox"` popup whose open/close is transition-animated.
|
|
81
|
+
* Staged cards reach it through BooleanField/ChoiceField; immediate-apply
|
|
82
|
+
* editors (the side-card prefs) bind it directly through onEdit.
|
|
83
|
+
* 双模式下拉框:皮肤激活时用原生 select,默认外观用自绘动画弹层。
|
|
84
|
+
*/
|
|
85
|
+
export function SelectField(props) {
|
|
86
|
+
const { id, options, value } = props;
|
|
87
|
+
const [open, setOpen] = useState(false);
|
|
88
|
+
const [closing, setClosing] = useState(false);
|
|
89
|
+
const [phase, setPhase] = useState('initial');
|
|
90
|
+
const [activeIndex, setActiveIndex] = useState(0);
|
|
91
|
+
const closeTimer = useRef(undefined);
|
|
92
|
+
const wrapRef = useRef(null);
|
|
93
|
+
const popupRef = useRef(null);
|
|
94
|
+
const currentIndex = () => {
|
|
95
|
+
const index = options.findIndex(option => option.value === value);
|
|
96
|
+
return index >= 0 ? index : 0;
|
|
97
|
+
};
|
|
98
|
+
const close = useCallback(() => {
|
|
99
|
+
if (closeTimer.current !== undefined)
|
|
100
|
+
clearTimeout(closeTimer.current);
|
|
101
|
+
setClosing(true);
|
|
102
|
+
closeTimer.current = setTimeout(() => {
|
|
103
|
+
setClosing(false);
|
|
104
|
+
setOpen(false);
|
|
105
|
+
}, SELECT_CLOSE_MS);
|
|
106
|
+
}, []);
|
|
107
|
+
const openPopup = () => {
|
|
108
|
+
if (closeTimer.current !== undefined)
|
|
109
|
+
clearTimeout(closeTimer.current);
|
|
110
|
+
setActiveIndex(currentIndex());
|
|
111
|
+
setPhase('initial');
|
|
112
|
+
setClosing(false);
|
|
113
|
+
setOpen(true);
|
|
114
|
+
};
|
|
115
|
+
const commit = (index) => {
|
|
116
|
+
const option = options[index];
|
|
117
|
+
if (option)
|
|
118
|
+
props.onEdit(option.value);
|
|
119
|
+
close();
|
|
120
|
+
};
|
|
121
|
+
const onTriggerClick = () => {
|
|
122
|
+
if (props.disabled)
|
|
123
|
+
return;
|
|
124
|
+
if (open && !closing)
|
|
125
|
+
close();
|
|
126
|
+
else
|
|
127
|
+
openPopup();
|
|
128
|
+
};
|
|
129
|
+
const onKeyDown = (event) => {
|
|
130
|
+
if (props.disabled)
|
|
131
|
+
return;
|
|
132
|
+
const count = options.length;
|
|
133
|
+
switch (event.key) {
|
|
134
|
+
case 'ArrowDown':
|
|
135
|
+
case 'ArrowUp':
|
|
136
|
+
case 'Enter':
|
|
137
|
+
case ' ':
|
|
138
|
+
event.preventDefault();
|
|
139
|
+
if (!open) {
|
|
140
|
+
openPopup();
|
|
141
|
+
}
|
|
142
|
+
else if (!closing) {
|
|
143
|
+
if (event.key === 'ArrowDown')
|
|
144
|
+
setActiveIndex(index => (index + 1) % count);
|
|
145
|
+
else if (event.key === 'ArrowUp')
|
|
146
|
+
setActiveIndex(index => (index - 1 + count) % count);
|
|
147
|
+
else
|
|
148
|
+
commit(activeIndex);
|
|
149
|
+
}
|
|
150
|
+
break;
|
|
151
|
+
case 'Escape':
|
|
152
|
+
if (open) {
|
|
153
|
+
event.preventDefault();
|
|
154
|
+
event.stopPropagation();
|
|
155
|
+
close();
|
|
156
|
+
}
|
|
157
|
+
break;
|
|
158
|
+
case 'Tab':
|
|
159
|
+
if (open)
|
|
160
|
+
close();
|
|
161
|
+
break;
|
|
162
|
+
}
|
|
163
|
+
};
|
|
164
|
+
useEffect(() => () => {
|
|
165
|
+
if (closeTimer.current !== undefined)
|
|
166
|
+
clearTimeout(closeTimer.current);
|
|
167
|
+
}, []);
|
|
168
|
+
useLayoutEffect(() => {
|
|
169
|
+
if (open && !closing && phase === 'initial') {
|
|
170
|
+
void popupRef.current?.offsetHeight;
|
|
171
|
+
setPhase('open');
|
|
172
|
+
}
|
|
173
|
+
}, [open, closing, phase]);
|
|
174
|
+
useEffect(() => {
|
|
175
|
+
if (!open)
|
|
176
|
+
return;
|
|
177
|
+
const onPointerDown = (event) => {
|
|
178
|
+
const target = event.target;
|
|
179
|
+
if (target instanceof Node && !wrapRef.current?.contains(target))
|
|
180
|
+
close();
|
|
181
|
+
};
|
|
182
|
+
document.addEventListener('pointerdown', onPointerDown);
|
|
183
|
+
return () => document.removeEventListener('pointerdown', onPointerDown);
|
|
184
|
+
}, [open, close]);
|
|
185
|
+
useEffect(() => {
|
|
186
|
+
if (props.disabled && open)
|
|
187
|
+
close();
|
|
188
|
+
}, [props.disabled, open, close]);
|
|
189
|
+
// 使用了皮肤则退回原生select样式防止样式冲突。
|
|
190
|
+
if (isSkinActive()) {
|
|
191
|
+
return (_jsx("select", { id: id, className: css.select, value: value, disabled: props.disabled, onChange: (event) => { props.onEdit(event.target.value); }, children: options.map(option => (_jsx("option", { value: option.value, children: option.label }, option.value))) }));
|
|
192
|
+
}
|
|
193
|
+
const label = options.find(option => option.value === value)?.label ?? '';
|
|
194
|
+
const popupClass = closing
|
|
195
|
+
? `${css.selectPopup} ${css.selectPopupClose}`
|
|
196
|
+
: phase === 'open'
|
|
197
|
+
? `${css.selectPopup} ${css.selectPopupOpen}`
|
|
198
|
+
: css.selectPopup;
|
|
199
|
+
return (_jsxs("div", { className: css.selectWrap, ref: wrapRef, children: [_jsxs("button", { type: "button", id: id, className: `${css.select} ${css.selectButton}`, disabled: props.disabled, "aria-haspopup": "listbox", "aria-expanded": open, "aria-activedescendant": open ? `${id}-o${activeIndex}` : undefined, "aria-invalid": props.invalid || undefined, onClick: onTriggerClick, onKeyDown: onKeyDown, children: [_jsx("span", { className: css.selectLabel, children: label }), _jsx("svg", { width: "14", height: "14", viewBox: "0 0 14 14", fill: "none", xmlns: "http://www.w3.org/2000/svg", className: open ? `${css.selectChevron} ${css.selectChevronOpen}` : css.selectChevron, "aria-hidden": "true", children: _jsx("path", { d: "M11.8486 5.5L11.4238 5.92383L8.69727 8.65137C8.44157 8.90706 8.21562 9.13382 8.01172 9.29785C7.79912 9.46883 7.55595 9.61756 7.25 9.66602C7.08435 9.69222 6.91565 9.69222 6.75 9.66602C6.44405 9.61756 6.20088 9.46883 5.98828 9.29785C5.78438 9.13382 5.55843 8.90706 5.30273 8.65137L2.57617 5.92383L2.15137 5.5L3 4.65137L3.42383 5.07617L6.15137 7.80273C6.42595 8.07732 6.59876 8.24849 6.74023 8.3623C6.87291 8.46904 6.92272 8.47813 6.9375 8.48047C6.97895 8.48703 7.02105 8.48703 7.0625 8.48047C7.07728 8.47813 7.12709 8.46904 7.25977 8.3623C7.40124 8.24849 7.57405 8.07732 7.84863 7.80273L10.5762 5.07617L11 4.65137L11.8486 5.5Z", fill: "currentColor" }) })] }), open
|
|
200
|
+
? (_jsx("div", { className: popupClass, role: "listbox", ref: popupRef, children: options.map((option, index) => (_jsx("div", { id: `${id}-o${index}`, role: "option", "aria-selected": option.value === value, className: `${css.selectOption}${option.value === value ? ` ${css.selectOptionSelected}` : ''}${index === activeIndex && !closing ? ` ${css.selectOptionActive}` : ''}`, onClick: () => { commit(index); }, children: option.label }, option.value))) }))
|
|
201
|
+
: null] }));
|
|
202
|
+
}
|
|
68
203
|
/** A staged boolean field: 继承 / 开 / 关. */
|
|
69
204
|
export function BooleanField(props) {
|
|
70
205
|
return (_jsxs("div", { className: css.field, children: [_jsxs("div", { className: css.head, children: [_jsx("label", { className: css.label, htmlFor: props.id, children: props.label }), props.overridden
|
|
71
206
|
? (_jsxs("span", { className: css.badges, children: [_jsx("span", { className: css.badge, children: props.overriddenLabel }), _jsx("button", { type: "button", className: css.reset, disabled: props.disabled, onClick: props.onReset, children: props.resetLabel })] }))
|
|
72
|
-
: null] }),
|
|
207
|
+
: null] }), _jsx(SelectField, { id: props.id, options: [
|
|
208
|
+
{ value: '', label: props.inheritLabel },
|
|
209
|
+
{ value: 'true', label: props.onLabel },
|
|
210
|
+
{ value: 'false', label: props.offLabel },
|
|
211
|
+
], value: props.text, disabled: props.disabled, invalid: props.invalid, onEdit: props.onEdit }), _jsx("p", { className: css.hint, children: props.hint })] }));
|
|
73
212
|
}
|
|
74
213
|
/** A staged enumerated field rendered as a select. */
|
|
75
214
|
export function ChoiceField(props) {
|
|
76
215
|
return (_jsxs("div", { className: css.field, children: [_jsxs("div", { className: css.head, children: [_jsx("label", { className: css.label, htmlFor: props.id, children: props.label }), props.overridden
|
|
77
216
|
? (_jsxs("span", { className: css.badges, children: [_jsx("span", { className: css.badge, children: props.overriddenLabel }), _jsx("button", { type: "button", className: css.reset, disabled: props.disabled, onClick: props.onReset, children: props.resetLabel })] }))
|
|
78
|
-
: null] }),
|
|
217
|
+
: null] }), _jsx(SelectField, { id: props.id, options: [{ value: '', label: props.inheritLabel }, ...props.choices], value: props.text, disabled: props.disabled, invalid: props.invalid, onEdit: props.onEdit }), _jsx("p", { className: props.invalid ? css.invalid : css.hint, children: props.invalid ? props.invalidLabel : props.hint })] }));
|
|
79
218
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/client/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,OAAO,KAAK,EAAE,aAAa,EAAwB,aAAa,EAAE,iBAAiB,EAAE,MAAM,wCAAwC,CAAA;AA6DnI,wEAAwE;AACxE,eAAO,MAAM,MAAM,UAA2E,CAAA;AAE9F,qEAAqE;AACrE,YAAY,EAAE,WAAW,EAAE,iBAAiB,EAAE,MAAM,oBAAoB,CAAA;AACxE,YAAY,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAA;AACrD,YAAY,EAAE,UAAU,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAA;AAC7D,YAAY,EAAE,mBAAmB,EAAE,oBAAoB,EAAE,MAAM,uBAAuB,CAAA;AACtF,YAAY,EAAE,uBAAuB,EAAE,MAAM,uBAAuB,CAAA;AACpE,YAAY,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAA;AAEnD,OAAO,QAAQ,qBAAqB,CAAC;IACnC,UAAU,OAAO;QACf;;;;WAIG;QACH,aAAa,CAAC,EAAE;YAAE,IAAI,CAAC,CAAC,EAAE,IAAI,EAAE,iBAAiB,CAAC,CAAC,CAAC,GAAG,aAAa,CAAC,CAAC,CAAC,CAAA;SAAE,CAAA;KAC1E;CACF;AAED;;;;;GAKG;AACH,wBAAgB,KAAK,CAAC,GAAG,EAAE,aAAa,GAAG,IAAI,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/client/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,OAAO,KAAK,EAAE,aAAa,EAAwB,aAAa,EAAE,iBAAiB,EAAE,MAAM,wCAAwC,CAAA;AA6DnI,wEAAwE;AACxE,eAAO,MAAM,MAAM,UAA2E,CAAA;AAE9F,qEAAqE;AACrE,YAAY,EAAE,WAAW,EAAE,iBAAiB,EAAE,MAAM,oBAAoB,CAAA;AACxE,YAAY,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAA;AACrD,YAAY,EAAE,UAAU,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAA;AAC7D,YAAY,EAAE,mBAAmB,EAAE,oBAAoB,EAAE,MAAM,uBAAuB,CAAA;AACtF,YAAY,EAAE,uBAAuB,EAAE,MAAM,uBAAuB,CAAA;AACpE,YAAY,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAA;AAEnD,OAAO,QAAQ,qBAAqB,CAAC;IACnC,UAAU,OAAO;QACf;;;;WAIG;QACH,aAAa,CAAC,EAAE;YAAE,IAAI,CAAC,CAAC,EAAE,IAAI,EAAE,iBAAiB,CAAC,CAAC,CAAC,GAAG,aAAa,CAAC,CAAC,CAAC,CAAA;SAAE,CAAA;KAC1E;CACF;AAED;;;;;GAKG;AACH,wBAAgB,KAAK,CAAC,GAAG,EAAE,aAAa,GAAG,IAAI,CAkN9C"}
|
|
@@ -241,6 +241,7 @@ export function apply(ctx) {
|
|
|
241
241
|
// when visible, and the hidden-state summon button is fixed-positioned.
|
|
242
242
|
const container = document.createElement('div');
|
|
243
243
|
container.dataset.dshPetRoot = '';
|
|
244
|
+
container.dataset.dshPlugin = 'pet';
|
|
244
245
|
document.body.appendChild(container);
|
|
245
246
|
const petRoot = createRoot(container);
|
|
246
247
|
petRoot.render(createElement(PetDockEntry, { ...injected(), t }));
|
|
@@ -18,6 +18,8 @@ export declare const zh: {
|
|
|
18
18
|
readonly 'pet.state.loading': '宠物正在赶来…';
|
|
19
19
|
readonly 'pet.state.error': '宠物迷路了(连接失败)';
|
|
20
20
|
readonly 'pet.openSessionHint': '点击跳转到对应会话';
|
|
21
|
+
readonly 'pet.moreSessions': '展开其余 {n} 个会话的气泡';
|
|
22
|
+
readonly 'pet.collapseSessions': '收起会话气泡';
|
|
21
23
|
readonly 'settings.title': '宠物';
|
|
22
24
|
readonly 'settings.description': '选择宠物并调整它的显示布局。';
|
|
23
25
|
readonly 'settings.pet': '宠物';
|
|
@@ -62,6 +64,8 @@ export declare const en: {
|
|
|
62
64
|
readonly 'pet.state.loading': 'The pet is on its way…';
|
|
63
65
|
readonly 'pet.state.error': 'The pet is lost (connection failed)';
|
|
64
66
|
readonly 'pet.openSessionHint': 'Click to jump to this session';
|
|
67
|
+
readonly 'pet.moreSessions': 'Expand {n} more session bubbles';
|
|
68
|
+
readonly 'pet.collapseSessions': 'Collapse session bubbles';
|
|
65
69
|
readonly 'settings.title': 'Pet';
|
|
66
70
|
readonly 'settings.description': 'Pick a pet and tune its display layout.';
|
|
67
71
|
readonly 'settings.pet': 'Pet';
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"locales.d.ts","sourceRoot":"","sources":["../../../src/client/locales.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,mDAAmD;AACnD,eAAO,MAAM,EAAE,QAAQ,CAAA;AAEvB,oBAAoB;AACpB,eAAO,MAAM,EAAE;aACb,UAAU,EAAE,IAAI;aAChB,UAAU,EAAE,IAAI;aAChB,YAAY,EAAE,IAAI;aAClB,aAAa,EAAE,IAAI;aACnB,qBAAqB,EAAE,OAAO;aAC9B,YAAY,EAAE,UAAU;aACxB,UAAU,EAAE,YAAY;aACxB,YAAY,EAAE,YAAY;aAC1B,YAAY,EAAE,UAAU;aACxB,mBAAmB,EAAE,SAAS;aAC9B,iBAAiB,EAAE,aAAa;aAChC,qBAAqB,EAAE,WAAW;
|
|
1
|
+
{"version":3,"file":"locales.d.ts","sourceRoot":"","sources":["../../../src/client/locales.ts"],"names":[],"mappings":"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"}
|
|
@@ -18,6 +18,8 @@ export const zh = {
|
|
|
18
18
|
'pet.state.loading': '宠物正在赶来…',
|
|
19
19
|
'pet.state.error': '宠物迷路了(连接失败)',
|
|
20
20
|
'pet.openSessionHint': '点击跳转到对应会话',
|
|
21
|
+
'pet.moreSessions': '展开其余 {n} 个会话的气泡',
|
|
22
|
+
'pet.collapseSessions': '收起会话气泡',
|
|
21
23
|
// 一级设置页(settings.section 席位)。
|
|
22
24
|
'settings.title': '宠物',
|
|
23
25
|
'settings.description': '选择宠物并调整它的显示布局。',
|
|
@@ -63,6 +65,8 @@ export const en = {
|
|
|
63
65
|
'pet.state.loading': 'The pet is on its way…',
|
|
64
66
|
'pet.state.error': 'The pet is lost (connection failed)',
|
|
65
67
|
'pet.openSessionHint': 'Click to jump to this session',
|
|
68
|
+
'pet.moreSessions': 'Expand {n} more session bubbles',
|
|
69
|
+
'pet.collapseSessions': 'Collapse session bubbles',
|
|
66
70
|
// First-level settings section (the `settings.section` seat).
|
|
67
71
|
'settings.title': 'Pet',
|
|
68
72
|
'settings.description': 'Pick a pet and tune its display layout.',
|
|
@@ -19,12 +19,10 @@ export declare function rowOfTrack(animation: PetAnimation): number;
|
|
|
19
19
|
* atlas coordinates here would drift each frame by the scale factor and
|
|
20
20
|
* render torn/overlapping frames.
|
|
21
21
|
*/
|
|
22
|
-
export declare function framePosition(cell: PetCell,
|
|
22
|
+
export declare function framePosition(cell: PetCell, row: number, col: number, scale?: number): {
|
|
23
23
|
x: number;
|
|
24
24
|
y: number;
|
|
25
25
|
};
|
|
26
|
-
/** Total duration of one track, ms. */
|
|
27
|
-
export declare function trackDuration(track: TrackDef): number;
|
|
28
26
|
/**
|
|
29
27
|
* Trim a track to the actual frame count of its row (the manifest's per-row
|
|
30
28
|
* counts are authoritative; this is a last-line guard against a definition
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"spritesheet.d.ts","sourceRoot":"","sources":["../../../src/client/spritesheet.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,EAAS,KAAK,YAAY,EAAE,MAAM,aAAa,CAAA;AACtD,OAAO,KAAK,EAAE,OAAO,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAA;AAE1D,qDAAqD;AACrD,MAAM,MAAM,QAAQ,GAAG,WAAW,CAAA;AAElC,mEAAmE;AACnE,wBAAgB,UAAU,CAAC,SAAS,EAAE,YAAY,GAAG,MAAM,CAG1D;AAED;;;;;;GAMG;AACH,wBAAgB,aAAa,CAAC,IAAI,EAAE,OAAO,EAAE,
|
|
1
|
+
{"version":3,"file":"spritesheet.d.ts","sourceRoot":"","sources":["../../../src/client/spritesheet.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,EAAS,KAAK,YAAY,EAAE,MAAM,aAAa,CAAA;AACtD,OAAO,KAAK,EAAE,OAAO,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAA;AAE1D,qDAAqD;AACrD,MAAM,MAAM,QAAQ,GAAG,WAAW,CAAA;AAElC,mEAAmE;AACnE,wBAAgB,UAAU,CAAC,SAAS,EAAE,YAAY,GAAG,MAAM,CAG1D;AAED;;;;;;GAMG;AACH,wBAAgB,aAAa,CAAC,IAAI,EAAE,OAAO,EAAE,GAAG,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,EAAE,KAAK,SAAI,GAAG;IAAE,CAAC,EAAE,MAAM,CAAC;IAAC,CAAC,EAAE,MAAM,CAAA;CAAE,CAE1G;AAED;;;;;GAKG;AACH,wBAAgB,SAAS,CAAC,KAAK,EAAE,QAAQ,EAAE,UAAU,EAAE,MAAM,GAAG,QAAQ,CAQvE"}
|
|
@@ -19,13 +19,9 @@ export function rowOfTrack(animation) {
|
|
|
19
19
|
* atlas coordinates here would drift each frame by the scale factor and
|
|
20
20
|
* render torn/overlapping frames.
|
|
21
21
|
*/
|
|
22
|
-
export function framePosition(cell,
|
|
22
|
+
export function framePosition(cell, row, col, scale = 1) {
|
|
23
23
|
return { x: -col * cell.width * scale, y: -row * cell.height * scale };
|
|
24
24
|
}
|
|
25
|
-
/** Total duration of one track, ms. */
|
|
26
|
-
export function trackDuration(track) {
|
|
27
|
-
return track.durations.reduce((sum, d) => sum + d, 0);
|
|
28
|
-
}
|
|
29
25
|
/**
|
|
30
26
|
* Trim a track to the actual frame count of its row (the manifest's per-row
|
|
31
27
|
* counts are authoritative; this is a last-line guard against a definition
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Loopback trust fence shared by the host route families: socket address,
|
|
3
|
+
* Host header, and browser same-origin markers. Packages receive this file as
|
|
4
|
+
* a generated copy via scripts/sync-shared.mjs; edit the shared source and
|
|
5
|
+
* re-run the sync instead of editing a copy.
|
|
6
|
+
*
|
|
7
|
+
* Semantics: RFC 5735 IPv4 127/8, ::1, IPv4-mapped ::ffff:127/8 (matching the
|
|
8
|
+
* remote-web-ui gate), localhost hostnames, plus the browser same-origin
|
|
9
|
+
* markers (sec-fetch-site and Origin) for the request-level fence.
|
|
10
|
+
* @module dsh-web-ui-shared/host/loopback
|
|
11
|
+
*/
|
|
12
|
+
import type { IncomingMessage } from 'node:http';
|
|
13
|
+
/** IPv4 127/8 predicate (four decimal octets, first == 127). */
|
|
14
|
+
export declare function isIPv4Loopback(v4: string): boolean;
|
|
15
|
+
/** Whether a socket remote address names the loopback range (127/8, ::1, IPv4-mapped). */
|
|
16
|
+
export declare function isLoopbackAddress(address: string | undefined): boolean;
|
|
17
|
+
/** Whether a normalized URL hostname names the loopback authority (localhost, [::1], 127/8). */
|
|
18
|
+
export declare function isLoopbackHostname(hostname: string): boolean;
|
|
19
|
+
/**
|
|
20
|
+
* Request-level trust fence: a loopback socket address AND a loopback Host
|
|
21
|
+
* header, plus browser same-origin markers. The socket address is
|
|
22
|
+
* authoritative; X-Forwarded-For is never trusted.
|
|
23
|
+
*/
|
|
24
|
+
export declare function isLoopbackRequest(request: IncomingMessage): boolean;
|
|
25
|
+
//# sourceMappingURL=loopback.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"loopback.d.ts","sourceRoot":"","sources":["../../src/loopback.ts"],"names":[],"mappings":"AACA;;;;;;;;;;GAUG;AAEH,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,WAAW,CAAA;AAEhD,gEAAgE;AAChE,wBAAgB,cAAc,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAKlD;AAED,0FAA0F;AAC1F,wBAAgB,iBAAiB,CAAC,OAAO,EAAE,MAAM,GAAG,SAAS,GAAG,OAAO,CAMtE;AAED,gGAAgG;AAChG,wBAAgB,kBAAkB,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAG5D;AAED;;;;GAIG;AACH,wBAAgB,iBAAiB,CAAC,OAAO,EAAE,eAAe,GAAG,OAAO,CAmBnE"}
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
// Generated by scripts/sync-shared.mjs from shared/host/loopback.ts. Do not edit this copy; edit the shared source and run "node scripts/sync-shared.mjs".
|
|
2
|
+
/**
|
|
3
|
+
* Loopback trust fence shared by the host route families: socket address,
|
|
4
|
+
* Host header, and browser same-origin markers. Packages receive this file as
|
|
5
|
+
* a generated copy via scripts/sync-shared.mjs; edit the shared source and
|
|
6
|
+
* re-run the sync instead of editing a copy.
|
|
7
|
+
*
|
|
8
|
+
* Semantics: RFC 5735 IPv4 127/8, ::1, IPv4-mapped ::ffff:127/8 (matching the
|
|
9
|
+
* remote-web-ui gate), localhost hostnames, plus the browser same-origin
|
|
10
|
+
* markers (sec-fetch-site and Origin) for the request-level fence.
|
|
11
|
+
* @module dsh-web-ui-shared/host/loopback
|
|
12
|
+
*/
|
|
13
|
+
/** IPv4 127/8 predicate (four decimal octets, first == 127). */
|
|
14
|
+
export function isIPv4Loopback(v4) {
|
|
15
|
+
const parts = v4.split('.');
|
|
16
|
+
return parts.length === 4
|
|
17
|
+
&& parts[0] === '127'
|
|
18
|
+
&& parts.every(part => /^\d{1,3}$/.test(part) && Number(part) <= 255);
|
|
19
|
+
}
|
|
20
|
+
/** Whether a socket remote address names the loopback range (127/8, ::1, IPv4-mapped). */
|
|
21
|
+
export function isLoopbackAddress(address) {
|
|
22
|
+
if (address === undefined)
|
|
23
|
+
return false;
|
|
24
|
+
const normalized = address.toLowerCase();
|
|
25
|
+
if (normalized === '::1')
|
|
26
|
+
return true;
|
|
27
|
+
if (normalized.startsWith('::ffff:'))
|
|
28
|
+
return isIPv4Loopback(normalized.slice('::ffff:'.length));
|
|
29
|
+
return isIPv4Loopback(normalized);
|
|
30
|
+
}
|
|
31
|
+
/** Whether a normalized URL hostname names the loopback authority (localhost, [::1], 127/8). */
|
|
32
|
+
export function isLoopbackHostname(hostname) {
|
|
33
|
+
if (hostname === 'localhost' || hostname === '[::1]')
|
|
34
|
+
return true;
|
|
35
|
+
return isIPv4Loopback(hostname);
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* Request-level trust fence: a loopback socket address AND a loopback Host
|
|
39
|
+
* header, plus browser same-origin markers. The socket address is
|
|
40
|
+
* authoritative; X-Forwarded-For is never trusted.
|
|
41
|
+
*/
|
|
42
|
+
export function isLoopbackRequest(request) {
|
|
43
|
+
if (!isLoopbackAddress(request.socket.remoteAddress))
|
|
44
|
+
return false;
|
|
45
|
+
const host = request.headers.host;
|
|
46
|
+
if (typeof host !== 'string')
|
|
47
|
+
return false;
|
|
48
|
+
let hostUrl;
|
|
49
|
+
try {
|
|
50
|
+
hostUrl = new URL('http://' + host);
|
|
51
|
+
}
|
|
52
|
+
catch {
|
|
53
|
+
return false;
|
|
54
|
+
}
|
|
55
|
+
if (!isLoopbackHostname(hostUrl.hostname))
|
|
56
|
+
return false;
|
|
57
|
+
if (request.headers['sec-fetch-site'] === 'cross-site')
|
|
58
|
+
return false;
|
|
59
|
+
const origin = request.headers.origin;
|
|
60
|
+
if (origin === undefined)
|
|
61
|
+
return true;
|
|
62
|
+
try {
|
|
63
|
+
return new URL(origin).host === hostUrl.host;
|
|
64
|
+
}
|
|
65
|
+
catch {
|
|
66
|
+
return false;
|
|
67
|
+
}
|
|
68
|
+
}
|
package/lib/types/registry.d.ts
CHANGED
|
@@ -169,6 +169,4 @@ export declare function loadPetRegistry(options: PetRegistryOptions): PetRegistr
|
|
|
169
169
|
export declare function petEntryView(entry: PetEntry): PetDefinition;
|
|
170
170
|
/** The absolute file a pet's atlas resolves to (host asset route). */
|
|
171
171
|
export declare function petAtlasFile(entry: PetEntry): string;
|
|
172
|
-
/** The directory basename of one entry (legacy asset URL alias, e.g. whale). */
|
|
173
|
-
export declare function petDirAlias(entry: PetEntry): string;
|
|
174
172
|
//# sourceMappingURL=registry.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"registry.d.ts","sourceRoot":"","sources":["../../src/registry.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"registry.d.ts","sourceRoot":"","sources":["../../src/registry.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AAMH,OAAO,KAAK,EAAE,aAAa,EAAE,YAAY,EAAE,MAAM,YAAY,CAAA;AAC7D,OAAO,EAAuB,KAAK,UAAU,EAAE,KAAK,kBAAkB,EAAE,MAAM,cAAc,CAAA;AAE5F,yDAAyD;AACzD,eAAO,MAAM,aAAa,EAAE,SAAS,YAAY,EAUhD,CAAA;AAED,6BAA6B;AAC7B,MAAM,WAAW,OAAO;IACtB,KAAK,EAAE,MAAM,CAAA;IACb,MAAM,EAAE,MAAM,CAAA;CACf;AAED,wDAAwD;AACxD,eAAO,MAAM,gBAAgB,EAAE,OAAqC,CAAA;AACpE,8CAA8C;AAC9C,eAAO,MAAM,mBAAmB,IAAI,CAAA;AACpC,2DAA2D;AAC3D,eAAO,MAAM,qBAAqB,IAAI,CAAA;AAEtC;;;GAGG;AACH,eAAO,MAAM,oBAAoB,EAAE,SAAS,MAAM,EAAgC,CAAA;AAElF,wEAAwE;AACxE,wBAAgB,cAAc,CAAC,aAAa,EAAE,MAAM,GAAG,MAAM,CAE5D;AAED,4EAA4E;AAC5E,wBAAgB,YAAY,CAAC,GAAG,GAAE,MAAM,CAAC,UAAwB,EAAE,IAAI,GAAE,MAAkB,GAAG,MAAM,CAQnG;AAeD,yDAAyD;AACzD,MAAM,WAAW,WAAW;IAC1B,+CAA+C;IAC/C,MAAM,EAAE,MAAM,EAAE,CAAA;IAChB,uDAAuD;IACvD,SAAS,EAAE,MAAM,EAAE,CAAA;IACnB,yEAAyE;IACzE,IAAI,EAAE,OAAO,CAAA;IACb,6DAA6D;IAC7D,QAAQ,CAAC,EAAE,YAAY,CAAA;CACxB;AAED,2DAA2D;AAC3D,eAAO,MAAM,sBAAsB,EAAE,MAAM,CAAC,YAAY,EAAE;IACxD,SAAS,EAAE,MAAM,EAAE,CAAA;IACnB,IAAI,EAAE,OAAO,CAAA;IACb,QAAQ,CAAC,EAAE,YAAY,CAAA;CACxB,CAUA,CAAA;AAED,2EAA2E;AAC3E,MAAM,WAAW,WAAW;IAC1B,2CAA2C;IAC3C,EAAE,EAAE,MAAM,CAAA;IACV,qEAAqE;IACrE,WAAW,EAAE,MAAM,CAAA;IACnB,4BAA4B;IAC5B,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,uDAAuD;IACvD,eAAe,EAAE,MAAM,CAAA;IACvB,+DAA+D;IAC/D,IAAI,CAAC,EAAE;QAAE,KAAK,CAAC,EAAE,MAAM,CAAC;QAAC,MAAM,CAAC,EAAE,MAAM,CAAA;KAAE,CAAA;IAC1C,sCAAsC;IACtC,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB;;;OAGG;IACH,MAAM,CAAC,EAAE,MAAM,EAAE,CAAA;IACjB,4EAA4E;IAC5E,MAAM,CAAC,EAAE,OAAO,CAAC,MAAM,CAAC,YAAY,EAAE,gBAAgB,CAAC,CAAC,CAAA;IACxD,wFAAwF;IACxF,SAAS,CAAC,EAAE,OAAO,CAAC,MAAM,CAAC,aAAa,EAAE,YAAY,EAAE,CAAC,CAAC,CAAA;IAC1D;;;;;OAKG;IACH,OAAO,CAAC,EAAE,kBAAkB,CAAA;CAC7B;AAED,uDAAuD;AACvD,MAAM,WAAW,gBAAgB;IAC/B,mEAAmE;IACnE,SAAS,CAAC,EAAE,MAAM,EAAE,CAAA;IACpB,+BAA+B;IAC/B,IAAI,CAAC,EAAE,OAAO,CAAA;IACd,6DAA6D;IAC7D,QAAQ,CAAC,EAAE,YAAY,CAAA;CACxB;AAED,sDAAsD;AACtD,MAAM,WAAW,aAAa;IAC5B,EAAE,EAAE,MAAM,CAAA;IACV,WAAW,EAAE,MAAM,CAAA;IACnB,WAAW,EAAE,MAAM,CAAA;IACnB,6BAA6B;IAC7B,IAAI,EAAE,OAAO,CAAA;IACb,uBAAuB;IACvB,OAAO,EAAE,MAAM,CAAA;IACf,wDAAwD;IACxD,IAAI,EAAE,MAAM,EAAE,CAAA;IACd,+DAA+D;IAC/D,SAAS,EAAE,MAAM,CAAA;IACjB,4EAA4E;IAC5E,MAAM,EAAE,MAAM,CAAC,YAAY,EAAE,WAAW,CAAC,CAAA;IACzC,sFAAsF;IACtF,SAAS,CAAC,EAAE,OAAO,CAAC,MAAM,CAAC,aAAa,EAAE,YAAY,EAAE,CAAC,CAAC,CAAA;IAC1D,iEAAiE;IACjE,QAAQ,EAAE,MAAM,CAAA;IAChB,oEAAoE;IACpE,WAAW,EAAE,MAAM,CAAA;CACpB;AAED,uDAAuD;AACvD,MAAM,WAAW,QAAS,SAAQ,aAAa;IAC7C,yDAAyD;IACzD,GAAG,EAAE,MAAM,CAAA;IACX,+DAA+D;IAC/D,eAAe,EAAE,MAAM,CAAA;IACvB,2EAA2E;IAC3E,OAAO,CAAC,EAAE,UAAU,CAAA;CACrB;AAED,iEAAiE;AACjE,MAAM,WAAW,WAAW;IAC1B,OAAO,EAAE,QAAQ,EAAE,CAAA;IACnB,QAAQ,EAAE,MAAM,EAAE,CAAA;IAClB,IAAI,CAAC,EAAE,EAAE,MAAM,GAAG,QAAQ,GAAG,SAAS,CAAA;IACtC,2EAA2E;IAC3E,YAAY,IAAI,QAAQ,CAAA;CACzB;AAED,wBAAwB;AACxB,MAAM,WAAW,kBAAkB;IACjC,iEAAiE;IACjE,WAAW,EAAE,MAAM,CAAA;IACnB,2DAA2D;IAC3D,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,yEAAyE;IACzE,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,oEAAoE;IACpE,KAAK,CAAC,EAAE,SAAS,WAAW,EAAE,CAAA;CAC/B;AAyCD;;;GAGG;AACH,wBAAgB,kBAAkB,CAChC,GAAG,EAAE,OAAO,EACZ,GAAG,EAAE,MAAM,EACX,OAAO,GAAE;IAAE,WAAW,CAAC,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,EAAE,MAAM,EAAE,CAAA;CAAO,GAC1D,QAAQ,GAAG,SAAS,CAyFtB;AAkCD;;;;;GAKG;AACH,wBAAgB,eAAe,CAAC,OAAO,EAAE,kBAAkB,GAAG,WAAW,CAgDxE;AAED,qEAAqE;AACrE,wBAAgB,YAAY,CAAC,KAAK,EAAE,QAAQ,GAAG,aAAa,CAc3D;AAED,sEAAsE;AACtE,wBAAgB,YAAY,CAAC,KAAK,EAAE,QAAQ,GAAG,MAAM,CAEpD"}
|
package/lib/types/registry.js
CHANGED
|
@@ -271,10 +271,18 @@ export function loadPetRegistry(options) {
|
|
|
271
271
|
}
|
|
272
272
|
}
|
|
273
273
|
for (const manifest of options.extra ?? []) {
|
|
274
|
-
const
|
|
274
|
+
const raw = manifest.spritesheetPath;
|
|
275
|
+
const dir = raw === undefined || isAbsolute(raw)
|
|
275
276
|
? join(packageRoot, 'assets', 'extra')
|
|
276
|
-
: dirname(resolve(packageRoot,
|
|
277
|
-
|
|
277
|
+
: dirname(resolve(packageRoot, raw));
|
|
278
|
+
// petAtlasFile joins entry.dir (already the spritesheet's parent when the
|
|
279
|
+
// path is package-relative) with entry.spritesheetPath, so the stored path
|
|
280
|
+
// must be the basename only — otherwise the directory segment is applied
|
|
281
|
+
// twice and the atlas 404s.
|
|
282
|
+
const source = raw === undefined || isAbsolute(raw)
|
|
283
|
+
? manifest
|
|
284
|
+
: { ...manifest, spritesheetPath: basename(raw) };
|
|
285
|
+
const entry = resolvePetManifest(source, dir, { assetPrefix, warnings });
|
|
278
286
|
if (entry === undefined)
|
|
279
287
|
continue;
|
|
280
288
|
if (byId.has(entry.id))
|
|
@@ -309,7 +317,3 @@ export function petEntryView(entry) {
|
|
|
309
317
|
export function petAtlasFile(entry) {
|
|
310
318
|
return join(entry.dir, entry.spritesheetPath);
|
|
311
319
|
}
|
|
312
|
-
/** The directory basename of one entry (legacy asset URL alias, e.g. whale). */
|
|
313
|
-
export function petDirAlias(entry) {
|
|
314
|
-
return basename(entry.dir);
|
|
315
|
-
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"remarks.d.ts","sourceRoot":"","sources":["../../src/remarks.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,wDAAwD;AACxD,MAAM,MAAM,UAAU,GAAG,KAAK,GAAG,aAAa,GAAG,MAAM,GAAG,cAAc,GAAG,UAAU,CAAA;AAErF,4CAA4C;AAC5C,eAAO,MAAM,YAAY,EAAE,SAAS,UAAU,EAM7C,CAAA;AAED,6EAA6E;AAC7E,MAAM,MAAM,UAAU,GAAG,OAAO,CAAC,MAAM,CAAC,UAAU,EAAE,MAAM,EAAE,CAAC,CAAC,CAAA;AAE9D,yEAAyE;AACzE,MAAM,MAAM,kBAAkB,GAAG,OAAO,CAAC,MAAM,CAAC,UAAU,EAAE,MAAM,GAAG,MAAM,EAAE,CAAC,CAAC,CAAA;AAE/E,2EAA2E;AAC3E,eAAO,MAAM,eAAe,MAAM,CAAA;AAClC,sCAAsC;AACtC,eAAO,MAAM,gBAAgB,KAAK,CAAA;AAElC;;;;;;GAMG;AACH,eAAO,MAAM,eAAe,EAAE,QAAQ,CAAC,MAAM,CAAC,UAAU,EAAE,SAAS,MAAM,EAAE,CAAC,
|
|
1
|
+
{"version":3,"file":"remarks.d.ts","sourceRoot":"","sources":["../../src/remarks.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,wDAAwD;AACxD,MAAM,MAAM,UAAU,GAAG,KAAK,GAAG,aAAa,GAAG,MAAM,GAAG,cAAc,GAAG,UAAU,CAAA;AAErF,4CAA4C;AAC5C,eAAO,MAAM,YAAY,EAAE,SAAS,UAAU,EAM7C,CAAA;AAED,6EAA6E;AAC7E,MAAM,MAAM,UAAU,GAAG,OAAO,CAAC,MAAM,CAAC,UAAU,EAAE,MAAM,EAAE,CAAC,CAAC,CAAA;AAE9D,yEAAyE;AACzE,MAAM,MAAM,kBAAkB,GAAG,OAAO,CAAC,MAAM,CAAC,UAAU,EAAE,MAAM,GAAG,MAAM,EAAE,CAAC,CAAC,CAAA;AAE/E,2EAA2E;AAC3E,eAAO,MAAM,eAAe,MAAM,CAAA;AAClC,sCAAsC;AACtC,eAAO,MAAM,gBAAgB,KAAK,CAAA;AAElC;;;;;;GAMG;AACH,eAAO,MAAM,eAAe,EAAE,QAAQ,CAAC,MAAM,CAAC,UAAU,EAAE,SAAS,MAAM,EAAE,CAAC,CA2F3E,CAAA;AAED,yEAAyE;AACzE,wBAAgB,aAAa,CAAC,IAAI,EAAE,UAAU,GAAG,MAAM,CAEtD;AAED;;;;;GAKG;AACH,wBAAgB,mBAAmB,CACjC,GAAG,EAAE,OAAO,EACZ,SAAS,GAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAe,GAC9C,UAAU,GAAG,SAAS,CAyBxB;AAED;;;;GAIG;AACH,qBAAa,YAAY;IACvB,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAgC;IACzD,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAuC;IAE7D,YAAY,SAAS,CAAC,EAAE,UAAU,EAMjC;IAED,qEAAqE;IACrE,IAAI,CAAC,IAAI,EAAE,UAAU,GAAG,SAAS,MAAM,EAAE,CAExC;IAED,gEAAgE;IAChE,IAAI,CAAC,IAAI,EAAE,UAAU,GAAG,MAAM,CAK7B;IAED,wFAAwF;IACxF,MAAM,CAAC,IAAI,EAAE,UAAU,EAAE,KAAK,EAAE,MAAM,GAAG,MAAM,CAG9C;CACF"}
|
package/lib/types/remarks.js
CHANGED
|
@@ -41,6 +41,12 @@ export const BUILTIN_REMARKS = {
|
|
|
41
41
|
'蹭蹭你的手心,这是回礼~',
|
|
42
42
|
'多摸摸我,亲密度会涨哦!',
|
|
43
43
|
'闭眼享受中,请勿打扰~',
|
|
44
|
+
'头再低一点,够不着了~',
|
|
45
|
+
'呼噜呼噜,声音都冒出来了',
|
|
46
|
+
'这手感,比小鱼干还上瘾',
|
|
47
|
+
'摸到第三下,满意',
|
|
48
|
+
'耳朵后面,别漏了……啊,舒服',
|
|
49
|
+
'被摸得尾巴都卷起来了',
|
|
44
50
|
],
|
|
45
51
|
petCooldown: [
|
|
46
52
|
'摸过头啦,让鲸鱼娘歇口气~',
|
|
@@ -53,6 +59,12 @@ export const BUILTIN_REMARKS = {
|
|
|
53
59
|
'歇一歇,摸摸的手感会更好哦~',
|
|
54
60
|
'咕……等我回个蓝~',
|
|
55
61
|
'让我先消化一下刚才的爱!',
|
|
62
|
+
'痒痒的,先让我缓一下……',
|
|
63
|
+
'再摸就掉线了,真的',
|
|
64
|
+
'库存的呼噜声用完了',
|
|
65
|
+
'手歇会儿,我也要补个蓝',
|
|
66
|
+
'舒服归舒服,得缓缓呀',
|
|
67
|
+
'再摸下去,我就要融化了',
|
|
56
68
|
],
|
|
57
69
|
feed: [
|
|
58
70
|
'呜哇!小鱼干好好吃!',
|
|
@@ -65,6 +77,12 @@ export const BUILTIN_REMARKS = {
|
|
|
65
77
|
'饱餐一顿,马上满血复活~',
|
|
66
78
|
'这个味道,是幸福的味道!',
|
|
67
79
|
'吃完了还不忘舔舔爪子~',
|
|
80
|
+
'这小鱼干,是今天的顶配',
|
|
81
|
+
'一口下去,精神头全回来了',
|
|
82
|
+
'脆!香!就是这个味儿',
|
|
83
|
+
'边吃边摇尾巴,形象不要了',
|
|
84
|
+
'好吃到眼睛都眯起来了',
|
|
85
|
+
'这块鱼干我记住了,懂我的',
|
|
68
86
|
],
|
|
69
87
|
feedCooldown: [
|
|
70
88
|
'吃饱啦,晚点再喂~',
|
|
@@ -77,6 +95,12 @@ export const BUILTIN_REMARKS = {
|
|
|
77
95
|
'肚皮已经鼓鼓的啦~',
|
|
78
96
|
'好吃是好吃,可也得节制呀~',
|
|
79
97
|
'等我饿了会告诉你哦~',
|
|
98
|
+
'胃说它满了,脑子说还能吃',
|
|
99
|
+
'这条得留着慢慢品',
|
|
100
|
+
'先消消食,待会儿再战',
|
|
101
|
+
'塞不下了,真塞不下了',
|
|
102
|
+
'闻着香,可惜没地方放了',
|
|
103
|
+
'嗝……这顿值了',
|
|
80
104
|
],
|
|
81
105
|
noTreats: [
|
|
82
106
|
'没有小鱼干了,多陪我工作一会儿吧~',
|
|
@@ -89,6 +113,12 @@ export const BUILTIN_REMARKS = {
|
|
|
89
113
|
'饿着肚子等你完成下一轮任务~',
|
|
90
114
|
'小鱼干藏在你的工作里,去找找看!',
|
|
91
115
|
'先工作后干饭,我们的约定哦~',
|
|
116
|
+
'粮仓见底,全靠感情撑着了',
|
|
117
|
+
'饿是真饿,活也是真得干',
|
|
118
|
+
'画饼充饥……不对,画鱼干充饥',
|
|
119
|
+
'没鱼干的日子,靠意志力过',
|
|
120
|
+
'下一轮任务,我闻到了鱼干味',
|
|
121
|
+
'先记账上,欠我两条,记住啦',
|
|
92
122
|
],
|
|
93
123
|
};
|
|
94
124
|
/** The legacy first line of one kind (direct callers' fallback copy). */
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"routes.d.ts","sourceRoot":"","sources":["../../src/routes.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAMH,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,iCAAiC,CAAA;AAC/D,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,cAAc,CAAA;
|
|
1
|
+
{"version":3,"file":"routes.d.ts","sourceRoot":"","sources":["../../src/routes.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAMH,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,iCAAiC,CAAA;AAC/D,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,cAAc,CAAA;AAK9C,+CAA+C;AAC/C,eAAO,MAAM,cAAc,aAAa,CAAA;AAExC,0EAA0E;AAC1E,eAAO,MAAM,gBAAgB,SAAS,CAAA;AAiOtC,kEAAkE;AAClE,wBAAgB,aAAa,CAAC,IAAI,EAAE;IAAE,OAAO,EAAE,UAAU,CAAA;CAAE,GAAG,QAAQ,EAAE,CAwCvE;AAGD,OAAO,EAAE,cAAc,EAAE,MAAM,eAAe,CAAA"}
|
package/lib/types/routes.js
CHANGED
|
@@ -12,6 +12,7 @@ import { existsSync } from 'node:fs';
|
|
|
12
12
|
import { readFile } from 'node:fs/promises';
|
|
13
13
|
import { join } from 'node:path';
|
|
14
14
|
import { petEntryView } from './registry.js';
|
|
15
|
+
import { isLoopbackRequest } from './loopback.js';
|
|
15
16
|
/** Browser-facing base path of the pet API. */
|
|
16
17
|
export const PET_API_PREFIX = '/api/pet';
|
|
17
18
|
/** Browser-facing base path of the pet asset routes ('/pet/<id>/...'). */
|
|
@@ -75,12 +76,21 @@ function readJsonBody(req) {
|
|
|
75
76
|
req.on('error', reject);
|
|
76
77
|
});
|
|
77
78
|
}
|
|
79
|
+
/** Shared route fence: the browser UI is a loopback client; LAN hosts stay out. */
|
|
80
|
+
function guard(req, res) {
|
|
81
|
+
if (isLoopbackRequest(req))
|
|
82
|
+
return true;
|
|
83
|
+
json(res, 403, { ok: false, error: 'forbidden: loopback-only' });
|
|
84
|
+
return false;
|
|
85
|
+
}
|
|
78
86
|
/** Wrap one async service call as a GET JSON route. */
|
|
79
87
|
function getRoute(path, run) {
|
|
80
88
|
return {
|
|
81
89
|
kind: 'exact',
|
|
82
90
|
path,
|
|
83
91
|
handler: (req, res) => {
|
|
92
|
+
if (!guard(req, res))
|
|
93
|
+
return;
|
|
84
94
|
if (!requireMethod(req, res, 'GET'))
|
|
85
95
|
return;
|
|
86
96
|
run().then((value) => json(res, 200, value), (error) => {
|
|
@@ -95,6 +105,8 @@ function postRoute(path, run) {
|
|
|
95
105
|
kind: 'exact',
|
|
96
106
|
path,
|
|
97
107
|
handler: (req, res) => {
|
|
108
|
+
if (!guard(req, res))
|
|
109
|
+
return Promise.resolve();
|
|
98
110
|
if (!requireMethod(req, res, 'POST'))
|
|
99
111
|
return Promise.resolve();
|
|
100
112
|
return readJsonBody(req).then((body) => {
|
|
@@ -127,6 +139,8 @@ function dirAliases(registry) {
|
|
|
127
139
|
function assetHandler(registry) {
|
|
128
140
|
const aliases = dirAliases(registry);
|
|
129
141
|
return (req, res) => {
|
|
142
|
+
if (!guard(req, res))
|
|
143
|
+
return;
|
|
130
144
|
if (req.method !== 'GET' && req.method !== 'HEAD') {
|
|
131
145
|
res.writeHead(405);
|
|
132
146
|
res.end();
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"service.d.ts","sourceRoot":"","sources":["../../src/service.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,MAAM,qBAAqB,CAAA;AAEtD,OAAO,KAAK,EAAE,cAAc,EAAE,eAAe,EAAE,cAAc,EAAE,MAAM,eAAe,CAAA;AACpF,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,aAAa,CAAA;AAQ9C,OAAO,EAAgC,KAAK,uBAAuB,EAAE,MAAM,aAAa,CAAA;AACxF,OAAO,EASL,KAAK,gBAAgB,
|
|
1
|
+
{"version":3,"file":"service.d.ts","sourceRoot":"","sources":["../../src/service.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,MAAM,qBAAqB,CAAA;AAEtD,OAAO,KAAK,EAAE,cAAc,EAAE,eAAe,EAAE,cAAc,EAAE,MAAM,eAAe,CAAA;AACpF,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,aAAa,CAAA;AAQ9C,OAAO,EAAgC,KAAK,uBAAuB,EAAE,MAAM,aAAa,CAAA;AACxF,OAAO,EASL,KAAK,gBAAgB,EACtB,MAAM,cAAc,CAAA;AACrB,OAAO,EAIL,KAAK,aAAa,EAClB,KAAK,WAAW,EAChB,KAAK,WAAW,EACjB,MAAM,eAAe,CAAA;AAEtB,OAAO,EAGL,KAAK,cAAc,EAEnB,KAAK,gBAAgB,EACtB,MAAM,YAAY,CAAA;AAEnB,4BAA4B;AAC5B,MAAM,WAAW,SAAS;IACxB,uBAAuB;IACvB,QAAQ,CAAC,EAAE,OAAO,CAAC,cAAc,CAAC,CAAA;IAClC,4BAA4B;IAC5B,KAAK,CAAC,EAAE,OAAO,CAAC,cAAc,CAAC,CAAA;IAC/B,4BAA4B;IAC5B,MAAM,CAAC,EAAE,OAAO,CAAC,WAAW,CAAC,CAAA;IAC7B,8DAA8D;IAC9D,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB,iEAAiE;IACjE,OAAO,CAAC,EAAE,OAAO,CAAA;IACjB,+EAA+E;IAC/E,QAAQ,CAAC,EAAE,WAAW,CAAA;IACtB,oEAAoE;IACpE,IAAI,CAAC,EAAE,SAAS,WAAW,EAAE,CAAA;CAC9B;AAED;;;;;;GAMG;AACH,MAAM,WAAW,kBAAkB;IACjC,2EAA2E;IAC3E,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,qBAAqB;IACrB,OAAO,EAAE,OAAO,CAAA;IAChB,4DAA4D;IAC5D,IAAI,EAAE,MAAM,CAAA;IACZ,yDAAyD;IACzD,KAAK,EAAE,MAAM,CAAA;IACb,wDAAwD;IACxD,MAAM,EAAE,MAAM,CAAA;IACd,iEAAiE;IACjE,OAAO,CAAC,EAAE,OAAO,CAAA;CAClB;AAED,2HAA2H;AAC3H,eAAO,MAAM,sBAAsB,QAAQ,CAAA;AAE3C;;;;;;;GAOG;AACH,MAAM,WAAW,cAAc;IAC7B,2EAA2E;IAC3E,SAAS,EAAE,MAAM,CAAA;IACjB,uDAAuD;IACvD,SAAS,EAAE,gBAAgB,CAAC,WAAW,CAAC,CAAA;IACxC,yCAAyC;IACzC,MAAM,EAAE,MAAM,CAAA;IACd,yCAAyC;IACzC,KAAK,EAAE,gBAAgB,CAAC,OAAO,CAAC,CAAA;CACjC;AAED,gFAAgF;AAChF,eAAO,MAAM,mBAAmB,KAAK,CAAA;AAErC,wCAAwC;AACxC,MAAM,WAAW,YAAY;IAC3B,SAAS,EAAE,gBAAgB,CAAC,WAAW,CAAC,CAAA;IACxC,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,KAAK,EAAE,gBAAgB,CAAC,OAAO,CAAC,CAAA;IAChC,aAAa,EAAE,OAAO,CAAA;IACtB;;;;;OAKG;IACH,QAAQ,CAAC,EAAE,cAAc,EAAE,CAAA;IAC3B,gCAAgC;IAChC,QAAQ,EAAE,eAAe,CAAA;IACzB,6BAA6B;IAC7B,OAAO,EAAE,gBAAgB,CAAA;IACzB,4CAA4C;IAC5C,GAAG,EAAE;QACH,mBAAmB;QACnB,EAAE,EAAE,MAAM,CAAA;QACV,iDAAiD;QACjD,WAAW,EAAE,MAAM,CAAA;QACnB,4BAA4B;QAC5B,WAAW,EAAE,MAAM,CAAA;KACpB,CAAA;IACD,yEAAyE;IACzE,IAAI,EAAE,MAAM,CAAA;IACZ,kCAAkC;IAClC,MAAM,EAAE;QACN,0BAA0B;QAC1B,OAAO,EAAE,MAAM,CAAA;QACf,iBAAiB;QACjB,GAAG,EAAE,MAAM,CAAA;KACZ,CAAA;IACD;;;;OAIG;IACH,OAAO,CAAC,EAAE,MAAM,CAAA;CACjB;AAED,gCAAgC;AAChC,MAAM,MAAM,iBAAiB,GAAG,uBAAuB,CAAA;AAEvD,OAAO,QAAQ,qBAAqB,CAAC;IACnC,UAAU,OAAO;QACf,GAAG,EAAE,UAAU,CAAA;KAChB;CACF;AAiBD;;;;;GAKG;AACH,qBAAa,UAAW,SAAQ,OAAO;IACrC,MAAM,CAAC,MAAM,EAAE,MAAM,EAAE,CAAK;IAE5B,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAiB;IACzC,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAgB;IAC5C,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAW;IAClC,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAa;IACtC,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAQ;IACnC,OAAO,CAAC,OAAO,CAAS;IACxB,OAAO,CAAC,eAAe,CAA0B;IACjD,kFAAkF;IAClF,OAAO,CAAC,cAAc,CAAqB;IAC3C;;;;OAIG;IACH,OAAO,CAAC,QAAQ,CAAC,eAAe,CAAsC;IAEtE,YAAY,GAAG,EAAE,OAAO,EAAE,MAAM,GAAE,SAAc,EA6B/C;IAED,uEAAuE;IACvE,SAAS,IAAI,OAAO,CAEnB;IAED,uCAAuC;IACjC,KAAK,IAAI,OAAO,CAAC,YAAY,CAAC,CAEnC;IAED,yDAAyD;IACzD,OAAO,IAAI,gBAAgB,CAE1B;IAED,2EAA2E;IACrE,IAAI,IAAI,OAAO,CAAC,aAAa,EAAE,CAAC,CAErC;IAED,gEAAgE;IAChE,gBAAgB,IAAI,WAAW,CAE9B;IAED,yCAAyC;IACzC,WAAW,IAAI,WAAW,CAAC,WAAW,CAAC,SAAS,CAAC,CAAC,MAAM,CAAC,CAAC,CAEzD;IAED,6CAA6C;IAC7C,aAAa,IAAI,MAAM,CAEtB;IAED,yEAAyE;IACzE,OAAO,CAAC,KAAK,GAAE,MAA6B,GAAG,MAAM,CAIpD;IAED,4EAA4E;IACtE,QAAQ,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC;QAAE,EAAE,EAAE,IAAI,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,GAAG;QAAE,EAAE,EAAE,KAAK,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,CAAC,CAQjG;IAED,uEAAuE;IACvE,UAAU,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,CAGjC;IAED,OAAO,CAAC,YAAY;IA4DpB,0EAA0E;IAC1E,OAAO,CAAC,UAAU;IAYlB;;;;OAIG;IACH,OAAO,CAAC,aAAa;IAqBrB,gCAAgC;IAC1B,QAAQ,CAAC,IAAI,EAAE,cAAc,GAAG,OAAO,CAAC,iBAAiB,CAAC,CAK/D;IAED,iCAAiC;IAC3B,UAAU,CAAC,OAAO,EAAE,OAAO,GAAG,OAAO,CAAC;QAAE,EAAE,EAAE,IAAI,CAAC;QAAC,OAAO,EAAE,gBAAgB,CAAA;KAAE,CAAC,CAKnF;IAED,wFAAwF;IAClF,SAAS,CAAC,KAAK,EAAE,OAAO,CAAC,gBAAgB,CAAC,GAAG,OAAO,CAAC;QAAE,EAAE,EAAE,IAAI,CAAC;QAAC,OAAO,EAAE,gBAAgB,CAAA;KAAE,CAAC,CASlG;IAED,2EAA2E;IACrE,OAAO,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC;QAAE,EAAE,EAAE,IAAI,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,GAAG;QAAE,EAAE,EAAE,KAAK,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,CAAC,CAO9F;IAED;;;;;OAKG;IACH,oBAAoB,CAAC,OAAO,EAAE,kBAAkB,GAAG,IAAI,CAiBtD;IAED,oFAAoF;IACpF,OAAO,CAAC,mBAAmB;IAe3B,qFAAqF;IACrF,OAAO,CAAC,UAAU;IAIlB,8EAA8E;IAC9E,OAAO,CAAC,gBAAgB;IAIxB,OAAO,CAAC,IAAI;IAuDZ,OAAO,CAAC,KAAK;CAOd"}
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@linxin666/dsh-pet",
|
|
3
3
|
"description": "Multi-pet companion plugin for the dsh web GUI: a registry-driven floating pet that reacts to model activity, with per-pet naming, petting/feeding interactions and an affinity score",
|
|
4
|
-
"version": "0.2.
|
|
4
|
+
"version": "0.2.2",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"engines": {
|
|
7
7
|
"node": "^22.19.0 || >=24.0.0"
|
|
@@ -72,7 +72,6 @@
|
|
|
72
72
|
"@types/react": "~18.3.1",
|
|
73
73
|
"@types/react-dom": "~18.3.0",
|
|
74
74
|
"jsdom": "29.1.1",
|
|
75
|
-
"lightningcss": "^1.32.0",
|
|
76
75
|
"react": "^18.2.0",
|
|
77
76
|
"react-dom": "^18.2.0",
|
|
78
77
|
"tsdown": "^0.22.2",
|