@lytjs/web 6.4.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/dist/index.js ADDED
@@ -0,0 +1,465 @@
1
+ // src/css-vars.ts
2
+ function normalizeVarName(name) {
3
+ return name.startsWith("--") ? name : `--${name}`;
4
+ }
5
+ function stripVarPrefix(name) {
6
+ return name.startsWith("--") ? name.slice(2) : name;
7
+ }
8
+ function setCSSVar(paramsOrElement, name, value, options) {
9
+ let element;
10
+ let varName;
11
+ let varValue;
12
+ let opts;
13
+ if (paramsOrElement instanceof HTMLElement) {
14
+ element = paramsOrElement;
15
+ varName = normalizeVarName(name);
16
+ varValue = value;
17
+ opts = options;
18
+ } else if ("element" in paramsOrElement) {
19
+ element = paramsOrElement.element;
20
+ varName = normalizeVarName(paramsOrElement.name);
21
+ varValue = paramsOrElement.value;
22
+ opts = paramsOrElement.options;
23
+ } else {
24
+ element = document.documentElement;
25
+ varName = normalizeVarName(paramsOrElement.name);
26
+ varValue = paramsOrElement.value;
27
+ opts = paramsOrElement.options;
28
+ }
29
+ if (!element) return;
30
+ if (varValue === null || varValue === void 0) {
31
+ element.style.removeProperty(varName);
32
+ return;
33
+ }
34
+ let finalValue;
35
+ if (typeof varValue === "number") {
36
+ finalValue = opts?.unit ? `${varValue}${opts.unit}` : String(varValue);
37
+ } else {
38
+ finalValue = varValue;
39
+ }
40
+ element.style.setProperty(varName, finalValue);
41
+ }
42
+ function getCSSVar(elementOrName, nameOrFallback, fallback) {
43
+ let element;
44
+ let varName;
45
+ let defaultValue;
46
+ if (typeof elementOrName === "string") {
47
+ element = document.documentElement;
48
+ varName = normalizeVarName(elementOrName);
49
+ defaultValue = nameOrFallback;
50
+ } else {
51
+ element = elementOrName;
52
+ varName = normalizeVarName(nameOrFallback);
53
+ defaultValue = fallback;
54
+ }
55
+ if (!element) return defaultValue ?? null;
56
+ const inlineValue = element.style.getPropertyValue(varName);
57
+ if (inlineValue) return inlineValue;
58
+ const computedStyle = window.getComputedStyle(element);
59
+ const value = computedStyle.getPropertyValue(varName).trim();
60
+ return value || defaultValue || null;
61
+ }
62
+ function setCSSVars(elementOrVars, vars) {
63
+ let element;
64
+ let variables;
65
+ if (elementOrVars instanceof HTMLElement) {
66
+ element = elementOrVars;
67
+ variables = vars ?? {};
68
+ } else {
69
+ element = document.documentElement;
70
+ variables = elementOrVars;
71
+ }
72
+ if (!element) return;
73
+ Object.entries(variables).forEach(([name, value]) => {
74
+ setCSSVar(element, name, value);
75
+ });
76
+ }
77
+ function getCSSVars(elementOrNames, names) {
78
+ let element;
79
+ let varNames;
80
+ if (elementOrNames instanceof HTMLElement) {
81
+ element = elementOrNames;
82
+ varNames = names ?? [];
83
+ } else {
84
+ element = document.documentElement;
85
+ varNames = elementOrNames;
86
+ }
87
+ const result = {};
88
+ varNames.forEach((name) => {
89
+ result[name] = getCSSVar(element, name);
90
+ });
91
+ return result;
92
+ }
93
+ function removeCSSVar(elementOrName, name) {
94
+ let element;
95
+ let varName;
96
+ if (typeof elementOrName === "string") {
97
+ element = document.documentElement;
98
+ varName = normalizeVarName(elementOrName);
99
+ } else {
100
+ element = elementOrName;
101
+ varName = normalizeVarName(name);
102
+ }
103
+ if (!element) return;
104
+ element.style.removeProperty(varName);
105
+ }
106
+ function removeCSSVars(elementOrNames, names) {
107
+ let element;
108
+ let varNames;
109
+ if (elementOrNames instanceof HTMLElement) {
110
+ element = elementOrNames;
111
+ varNames = names ?? [];
112
+ } else {
113
+ element = document.documentElement;
114
+ varNames = elementOrNames;
115
+ }
116
+ if (!element) return;
117
+ varNames.forEach((name) => {
118
+ element.style.removeProperty(normalizeVarName(name));
119
+ });
120
+ }
121
+ function hasCSSVar(elementOrName, name) {
122
+ let element;
123
+ let varName;
124
+ if (typeof elementOrName === "string") {
125
+ element = document.documentElement;
126
+ varName = normalizeVarName(elementOrName);
127
+ } else {
128
+ element = elementOrName;
129
+ varName = normalizeVarName(name);
130
+ }
131
+ if (!element) return false;
132
+ if (element.style.getPropertyValue(varName)) return true;
133
+ const computedStyle = window.getComputedStyle(element);
134
+ return !!computedStyle.getPropertyValue(varName).trim();
135
+ }
136
+ function getAllCSSVars(element) {
137
+ const el = element ?? document.documentElement;
138
+ if (!el) return {};
139
+ const result = {};
140
+ const computedStyle = window.getComputedStyle(el);
141
+ for (let i = 0; i < computedStyle.length; i++) {
142
+ const prop = computedStyle[i];
143
+ if (prop.startsWith("--")) {
144
+ const value = computedStyle.getPropertyValue(prop).trim();
145
+ if (value) {
146
+ result[prop] = value;
147
+ }
148
+ }
149
+ }
150
+ return result;
151
+ }
152
+ function toggleCSSVar(elementOrName, nameOrValue1, value1OrValue2, value2) {
153
+ let element;
154
+ let varName;
155
+ let val1;
156
+ let val2;
157
+ if (typeof elementOrName === "string") {
158
+ element = document.documentElement;
159
+ varName = normalizeVarName(elementOrName);
160
+ val1 = nameOrValue1;
161
+ val2 = value1OrValue2;
162
+ } else {
163
+ element = elementOrName;
164
+ varName = normalizeVarName(nameOrValue1);
165
+ val1 = value1OrValue2;
166
+ val2 = value2;
167
+ }
168
+ const currentValue = getCSSVar(element, varName);
169
+ const newValue = currentValue === val1 ? val2 : val1;
170
+ setCSSVar(element, varName, newValue);
171
+ return newValue;
172
+ }
173
+ var _CSSVarObserver = class _CSSVarObserver {
174
+ constructor(element) {
175
+ this.observer = null;
176
+ this.callbacks = /* @__PURE__ */ new Map();
177
+ /**
178
+ * 检查变量变化
179
+ * FIX: P2-v11-37 添加最大条目限制,防止 lastValues Map 无限增长
180
+ */
181
+ this.lastValues = /* @__PURE__ */ new Map();
182
+ this.element = element ?? document.documentElement;
183
+ }
184
+ /**
185
+ * 开始观察 CSS 变量变化
186
+ *
187
+ * @param names - 要观察的变量名数组(可选,不指定则观察所有)
188
+ */
189
+ observe(names) {
190
+ if (this.observer) return;
191
+ const targetNames = names?.map(normalizeVarName);
192
+ this.observer = new MutationObserver((mutations) => {
193
+ mutations.forEach((mutation) => {
194
+ if (mutation.type === "attributes" && mutation.attributeName === "style") {
195
+ this.checkChanges(targetNames);
196
+ }
197
+ });
198
+ });
199
+ this.observer.observe(this.element, {
200
+ attributes: true,
201
+ attributeFilter: ["style"]
202
+ });
203
+ }
204
+ /**
205
+ * 停止观察
206
+ */
207
+ disconnect() {
208
+ this.observer?.disconnect();
209
+ this.observer = null;
210
+ }
211
+ /**
212
+ * 订阅变量变化
213
+ *
214
+ * @param name - 变量名
215
+ * @param callback - 变化回调
216
+ * @returns 取消订阅函数
217
+ */
218
+ subscribe(name, callback) {
219
+ const varName = normalizeVarName(name);
220
+ if (!this.callbacks.has(varName)) {
221
+ this.callbacks.set(varName, /* @__PURE__ */ new Set());
222
+ }
223
+ this.callbacks.get(varName).add(callback);
224
+ return () => {
225
+ this.callbacks.get(varName)?.delete(callback);
226
+ };
227
+ }
228
+ checkChanges(targetNames) {
229
+ const namesToCheck = targetNames ?? Array.from(this.callbacks.keys());
230
+ if (this.lastValues.size > _CSSVarObserver.MAX_LAST_VALUES_SIZE) {
231
+ const activeNames = new Set(this.callbacks.keys());
232
+ for (const key of this.lastValues.keys()) {
233
+ if (!activeNames.has(key)) {
234
+ this.lastValues.delete(key);
235
+ }
236
+ }
237
+ }
238
+ namesToCheck.forEach((name) => {
239
+ const currentValue = getCSSVar(this.element, name);
240
+ const lastValue = this.lastValues.get(name);
241
+ if (currentValue !== lastValue) {
242
+ this.lastValues.set(name, currentValue);
243
+ const callbacks = this.callbacks.get(name);
244
+ if (callbacks) {
245
+ callbacks.forEach((cb) => cb(currentValue, lastValue ?? null, name));
246
+ }
247
+ }
248
+ });
249
+ }
250
+ };
251
+ /** lastValues 最大条目数 */
252
+ _CSSVarObserver.MAX_LAST_VALUES_SIZE = 500;
253
+ var CSSVarObserver = _CSSVarObserver;
254
+ var ThemeManager = class {
255
+ constructor(element) {
256
+ this.themes = /* @__PURE__ */ new Map();
257
+ this.currentTheme = null;
258
+ this.element = element ?? document.documentElement;
259
+ }
260
+ /**
261
+ * 注册主题
262
+ *
263
+ * @param name - 主题名称
264
+ * @param config - 主题配置(CSS 变量键值对)
265
+ */
266
+ register(name, config) {
267
+ this.themes.set(name, config);
268
+ }
269
+ /**
270
+ * 应用主题
271
+ *
272
+ * @param name - 主题名称
273
+ */
274
+ apply(name) {
275
+ const theme = this.themes.get(name);
276
+ if (!theme) return false;
277
+ setCSSVars(this.element, theme);
278
+ this.currentTheme = name;
279
+ this.element.setAttribute("data-theme", name);
280
+ return true;
281
+ }
282
+ /**
283
+ * 获取当前主题名称
284
+ */
285
+ getCurrentTheme() {
286
+ return this.currentTheme;
287
+ }
288
+ /**
289
+ * 获取已注册的主题列表
290
+ */
291
+ getRegisteredThemes() {
292
+ return Array.from(this.themes.keys());
293
+ }
294
+ /**
295
+ * 检查主题是否存在
296
+ */
297
+ hasTheme(name) {
298
+ return this.themes.has(name);
299
+ }
300
+ /**
301
+ * 获取主题配置
302
+ */
303
+ getThemeConfig(name) {
304
+ return this.themes.get(name);
305
+ }
306
+ };
307
+
308
+ // src/resize-observer.ts
309
+ var ResizeObserverManager = class {
310
+ constructor(callback) {
311
+ this.observer = null;
312
+ this.observedElements = /* @__PURE__ */ new Set();
313
+ this.isConnected = false;
314
+ this.callback = callback;
315
+ if (typeof ResizeObserver === "undefined") {
316
+ if (__DEV__) {
317
+ console.warn(
318
+ "[lytjs/resize-observer] ResizeObserver is not supported in this environment."
319
+ );
320
+ }
321
+ return;
322
+ }
323
+ this.observer = new ResizeObserver((entries) => {
324
+ const activeEntries = entries.filter((entry) => this.observedElements.has(entry.target));
325
+ if (activeEntries.length > 0) {
326
+ this.callback(activeEntries);
327
+ }
328
+ });
329
+ }
330
+ /**
331
+ * 开始观察元素
332
+ *
333
+ * @param target - 要观察的目标元素
334
+ * @param options - 观察选项
335
+ * @returns 是否成功开始观察
336
+ */
337
+ observe(target, options) {
338
+ if (!this.observer) {
339
+ if (__DEV__) {
340
+ console.warn("[lytjs/resize-observer] Cannot observe: ResizeObserver is not available.");
341
+ }
342
+ return false;
343
+ }
344
+ if (this.observedElements.has(target)) {
345
+ if (__DEV__) {
346
+ console.warn("[lytjs/resize-observer] Element is already being observed.");
347
+ }
348
+ return false;
349
+ }
350
+ try {
351
+ this.observer.observe(target, options);
352
+ this.observedElements.add(target);
353
+ this.isConnected = true;
354
+ return true;
355
+ } catch (err) {
356
+ if (__DEV__) {
357
+ console.error("[lytjs/resize-observer] Error observing element:", err);
358
+ }
359
+ return false;
360
+ }
361
+ }
362
+ /**
363
+ * 停止观察指定元素
364
+ *
365
+ * @param target - 要停止观察的目标元素
366
+ * @returns 是否成功停止观察
367
+ */
368
+ unobserve(target) {
369
+ if (!this.observer) {
370
+ return false;
371
+ }
372
+ if (!this.observedElements.has(target)) {
373
+ return false;
374
+ }
375
+ try {
376
+ this.observer.unobserve(target);
377
+ this.observedElements.delete(target);
378
+ if (this.observedElements.size === 0) {
379
+ this.isConnected = false;
380
+ }
381
+ return true;
382
+ } catch (err) {
383
+ if (__DEV__) {
384
+ console.error("[lytjs/resize-observer] Error unobserving element:", err);
385
+ }
386
+ return false;
387
+ }
388
+ }
389
+ /**
390
+ * 停止观察所有元素并断开连接
391
+ *
392
+ * FIX: P2-5 这是关键方法,确保在组件卸载时调用此方法
393
+ */
394
+ disconnect() {
395
+ if (!this.observer) {
396
+ return;
397
+ }
398
+ try {
399
+ this.observer.disconnect();
400
+ this.observedElements.clear();
401
+ this.isConnected = false;
402
+ } catch (err) {
403
+ if (__DEV__) {
404
+ console.error("[lytjs/resize-observer] Error disconnecting observer:", err);
405
+ }
406
+ }
407
+ }
408
+ /**
409
+ * 检查是否正在观察指定元素
410
+ *
411
+ * @param target - 要检查的目标元素
412
+ * @returns 是否正在观察
413
+ */
414
+ isObserving(target) {
415
+ return this.observedElements.has(target);
416
+ }
417
+ /**
418
+ * 获取当前观察的元素数量
419
+ */
420
+ get observedCount() {
421
+ return this.observedElements.size;
422
+ }
423
+ /**
424
+ * 检查观察者是否已连接(正在观察至少一个元素)
425
+ */
426
+ get connected() {
427
+ return this.isConnected;
428
+ }
429
+ /**
430
+ * 检查 ResizeObserver 是否可用
431
+ */
432
+ get isAvailable() {
433
+ return this.observer !== null;
434
+ }
435
+ };
436
+ function useResizeObserver(target, callback, options) {
437
+ const manager = new ResizeObserverManager(callback);
438
+ manager.observe(target, options);
439
+ return () => {
440
+ manager.disconnect();
441
+ };
442
+ }
443
+ function supportsResizeObserver() {
444
+ return typeof ResizeObserver !== "undefined";
445
+ }
446
+ if (__DEV__) {
447
+ const managerRegistry = /* @__PURE__ */ new WeakSet();
448
+ const OriginalManager = ResizeObserverManager;
449
+ ResizeObserverManager = class extends OriginalManager {
450
+ constructor(callback) {
451
+ super(callback);
452
+ managerRegistry.add(this);
453
+ }
454
+ };
455
+ globalThis.__getResizeObserverStats = () => {
456
+ return {
457
+ activeManagers: 0,
458
+ totalObservedElements: 0
459
+ };
460
+ };
461
+ }
462
+
463
+ export { CSSVarObserver, ResizeObserverManager, ThemeManager, getAllCSSVars, getCSSVar, getCSSVars, hasCSSVar, normalizeVarName, removeCSSVar, removeCSSVars, setCSSVar, setCSSVars, stripVarPrefix, supportsResizeObserver, toggleCSSVar, useResizeObserver };
464
+ //# sourceMappingURL=index.js.map
465
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/css-vars.ts","../src/resize-observer.ts"],"names":[],"mappings":"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","file":"index.js","sourcesContent":["/**\r\n * @lytjs/web - CSS 变量支持模块\r\n *\r\n * 提供增强的 CSS 自定义属性(CSS Variables)支持,\r\n * 包括设置、获取、监听 CSS 变量变化等功能\r\n *\r\n * @module @lytjs/web/css-vars\r\n * @version 6.0.0\r\n */\r\n\r\n// ============================================================\r\n// 类型定义\r\n// ============================================================\r\n\r\n/**\r\n * CSS 变量值类型\r\n */\r\nexport type CSSVarValue = string | number | null | undefined;\r\n\r\n/**\r\n * CSS 变量变更回调\r\n */\r\nexport type CSSVarChangeCallback = (\r\n newValue: string | null,\r\n oldValue: string | null,\r\n variable: string,\r\n) => void;\r\n\r\n/**\r\n * CSS 变量配置选项\r\n */\r\nexport interface CSSVarOptions {\r\n /** 是否继承父元素的值 */\r\n inherit?: boolean;\r\n /** 单位(用于数值类型) */\r\n unit?: string;\r\n}\r\n\r\n// ============================================================\r\n// 核心工具函数\r\n// ============================================================\r\n\r\n/**\r\n * 规范化 CSS 变量名\r\n * 确保变量名以 -- 开头\r\n *\r\n * @param name - 变量名(可带或不带 -- 前缀)\r\n * @returns 规范化后的变量名\r\n * @example\r\n * ```ts\r\n * normalizeVarName('primary-color') // '--primary-color'\r\n * normalizeVarName('--primary-color') // '--primary-color'\r\n * ```\r\n */\r\nexport function normalizeVarName(name: string): string {\r\n return name.startsWith('--') ? name : `--${name}`;\r\n}\r\n\r\n/**\r\n * 移除 CSS 变量名的 -- 前缀\r\n *\r\n * @param name - 变量名\r\n * @returns 无前缀的变量名\r\n * @example\r\n * ```ts\r\n * stripVarPrefix('--primary-color') // 'primary-color'\r\n * stripVarPrefix('primary-color') // 'primary-color'\r\n * ```\r\n */\r\nexport function stripVarPrefix(name: string): string {\r\n return name.startsWith('--') ? name.slice(2) : name;\r\n}\r\n\r\n/**\r\n * setCSSVar 参数对象 - 指定元素上的 CSS 变量\r\n */\r\nexport interface SetCSSVarWithElementOptions {\r\n /** 目标元素 */\r\n element: HTMLElement;\r\n /** 变量名 */\r\n name: string;\r\n /** 变量值(null/undefined 表示移除) */\r\n value?: CSSVarValue;\r\n /** 配置选项 */\r\n options?: CSSVarOptions;\r\n}\r\n\r\n/**\r\n * setCSSVar 参数对象 - 全局 CSS 变量\r\n */\r\nexport interface SetCSSVarGlobalOptions {\r\n /** 变量名 */\r\n name: string;\r\n /** 变量值(null/undefined 表示移除) */\r\n value?: CSSVarValue;\r\n /** 配置选项 */\r\n options?: CSSVarOptions;\r\n}\r\n\r\n/**\r\n * 设置 CSS 变量\r\n *\r\n * @param params - 参数对象\r\n * @example\r\n * ```ts\r\n * // 设置全局变量\r\n * setCSSVar({ name: '--primary-color', value: '#007bff' })\r\n *\r\n * // 设置元素变量\r\n * setCSSVar({ element: myElement, name: 'font-size', value: 16, options: { unit: 'px' } })\r\n *\r\n * // 移除变量\r\n * setCSSVar({ element: myElement, name: '--old-var', value: null })\r\n * ```\r\n */\r\nexport function setCSSVar(params: SetCSSVarWithElementOptions): void;\r\nexport function setCSSVar(params: SetCSSVarGlobalOptions): void;\r\n/** @deprecated 使用对象参数形式 setCSSVar({ element, name, value }) 替代 */\r\nexport function setCSSVar(\r\n element: HTMLElement,\r\n name: string,\r\n value?: CSSVarValue,\r\n options?: CSSVarOptions,\r\n): void;\r\nexport function setCSSVar(\r\n paramsOrElement: SetCSSVarWithElementOptions | SetCSSVarGlobalOptions | HTMLElement,\r\n name?: string,\r\n value?: CSSVarValue,\r\n options?: CSSVarOptions,\r\n): void {\r\n let element: HTMLElement;\r\n let varName: string;\r\n let varValue: CSSVarValue;\r\n let opts: CSSVarOptions | undefined;\r\n\r\n if (paramsOrElement instanceof HTMLElement) {\r\n // 向后兼容的位置参数调用方式\r\n element = paramsOrElement;\r\n varName = normalizeVarName(name!);\r\n varValue = value;\r\n opts = options;\r\n } else if ('element' in paramsOrElement) {\r\n // 对象参数:指定元素\r\n element = paramsOrElement.element;\r\n varName = normalizeVarName(paramsOrElement.name);\r\n varValue = paramsOrElement.value;\r\n opts = paramsOrElement.options;\r\n } else {\r\n // 对象参数:全局设置\r\n element = document.documentElement;\r\n varName = normalizeVarName(paramsOrElement.name);\r\n varValue = paramsOrElement.value;\r\n opts = paramsOrElement.options;\r\n }\r\n\r\n if (!element) return;\r\n\r\n // 处理 null/undefined(移除变量)\r\n if (varValue === null || varValue === undefined) {\r\n element.style.removeProperty(varName);\r\n return;\r\n }\r\n\r\n // 处理数值和单位\r\n let finalValue: string;\r\n if (typeof varValue === 'number') {\r\n finalValue = opts?.unit ? `${varValue}${opts.unit}` : String(varValue);\r\n } else {\r\n finalValue = varValue;\r\n }\r\n\r\n element.style.setProperty(varName, finalValue);\r\n}\r\n\r\n/**\r\n * 获取 CSS 变量值\r\n *\r\n * @param element - 目标元素(默认为 document.documentElement)\r\n * @param name - 变量名\r\n * @param fallback - 默认值(变量不存在时返回)\r\n * @returns 变量值或默认值\r\n * @example\r\n * ```ts\r\n * // 获取全局变量\r\n * const color = getCSSVar('--primary-color')\r\n *\r\n * // 获取元素变量\r\n * const size = getCSSVar(myElement, 'font-size', '16px')\r\n * ```\r\n */\r\nexport function getCSSVar(name: string, fallback?: string): string | null;\r\nexport function getCSSVar(element: HTMLElement, name: string, fallback?: string): string | null;\r\nexport function getCSSVar(\r\n elementOrName: HTMLElement | string,\r\n nameOrFallback?: string,\r\n fallback?: string,\r\n): string | null {\r\n // 处理重载签名\r\n let element: HTMLElement;\r\n let varName: string;\r\n let defaultValue: string | undefined;\r\n\r\n if (typeof elementOrName === 'string') {\r\n element = document.documentElement;\r\n varName = normalizeVarName(elementOrName);\r\n defaultValue = nameOrFallback;\r\n } else {\r\n element = elementOrName;\r\n varName = normalizeVarName(nameOrFallback as string);\r\n defaultValue = fallback;\r\n }\r\n\r\n if (!element) return defaultValue ?? null;\r\n\r\n // 首先尝试从元素的 style 属性获取\r\n const inlineValue = element.style.getPropertyValue(varName);\r\n if (inlineValue) return inlineValue;\r\n\r\n // 然后从计算样式获取\r\n const computedStyle = window.getComputedStyle(element);\r\n const value = computedStyle.getPropertyValue(varName).trim();\r\n\r\n return value || defaultValue || null;\r\n}\r\n\r\n/**\r\n * 批量设置 CSS 变量\r\n *\r\n * @param element - 目标元素(默认为 document.documentElement)\r\n * @param vars - 变量键值对对象\r\n * @example\r\n * ```ts\r\n * setCSSVars({\r\n * '--primary-color': '#007bff',\r\n * '--font-size': '16px',\r\n * '--spacing': 8,\r\n * })\r\n * ```\r\n */\r\nexport function setCSSVars(vars: Record<string, CSSVarValue>): void;\r\nexport function setCSSVars(element: HTMLElement, vars: Record<string, CSSVarValue>): void;\r\nexport function setCSSVars(\r\n elementOrVars: HTMLElement | Record<string, CSSVarValue>,\r\n vars?: Record<string, CSSVarValue>,\r\n): void {\r\n let element: HTMLElement;\r\n let variables: Record<string, CSSVarValue>;\r\n\r\n if (elementOrVars instanceof HTMLElement) {\r\n element = elementOrVars;\r\n variables = vars ?? {};\r\n } else {\r\n element = document.documentElement;\r\n variables = elementOrVars;\r\n }\r\n\r\n if (!element) return;\r\n\r\n Object.entries(variables).forEach(([name, value]) => {\r\n setCSSVar(element, name, value);\r\n });\r\n}\r\n\r\n/**\r\n * 批量获取 CSS 变量\r\n *\r\n * @param names - 变量名数组\r\n * @returns 变量值对象\r\n * @example\r\n * ```ts\r\n * const values = getCSSVars(['--primary-color', '--font-size'])\r\n * // { '--primary-color': '#007bff', '--font-size': '16px' }\r\n * ```\r\n */\r\nexport function getCSSVars(names: string[]): Record<string, string | null>;\r\nexport function getCSSVars(element: HTMLElement, names: string[]): Record<string, string | null>;\r\nexport function getCSSVars(\r\n elementOrNames: HTMLElement | string[],\r\n names?: string[],\r\n): Record<string, string | null> {\r\n let element: HTMLElement;\r\n let varNames: string[];\r\n\r\n if (elementOrNames instanceof HTMLElement) {\r\n element = elementOrNames;\r\n varNames = names ?? [];\r\n } else {\r\n element = document.documentElement;\r\n varNames = elementOrNames;\r\n }\r\n\r\n const result: Record<string, string | null> = {};\r\n varNames.forEach((name) => {\r\n result[name] = getCSSVar(element, name);\r\n });\r\n return result;\r\n}\r\n\r\n/**\r\n * 移除 CSS 变量\r\n *\r\n * @param element - 目标元素(默认为 document.documentElement)\r\n * @param name - 变量名\r\n * @example\r\n * ```ts\r\n * removeCSSVar('--old-variable')\r\n * removeCSSVar(myElement, '--old-variable')\r\n * ```\r\n */\r\nexport function removeCSSVar(name: string): void;\r\nexport function removeCSSVar(element: HTMLElement, name: string): void;\r\nexport function removeCSSVar(elementOrName: HTMLElement | string, name?: string): void {\r\n let element: HTMLElement;\r\n let varName: string;\r\n\r\n if (typeof elementOrName === 'string') {\r\n element = document.documentElement;\r\n varName = normalizeVarName(elementOrName);\r\n } else {\r\n element = elementOrName;\r\n varName = normalizeVarName(name as string);\r\n }\r\n\r\n if (!element) return;\r\n element.style.removeProperty(varName);\r\n}\r\n\r\n/**\r\n * 批量移除 CSS 变量\r\n *\r\n * @param names - 变量名数组\r\n * @example\r\n * ```ts\r\n * removeCSSVars(['--var1', '--var2'])\r\n * ```\r\n */\r\nexport function removeCSSVars(names: string[]): void;\r\nexport function removeCSSVars(element: HTMLElement, names: string[]): void;\r\nexport function removeCSSVars(elementOrNames: HTMLElement | string[], names?: string[]): void {\r\n let element: HTMLElement;\r\n let varNames: string[];\r\n\r\n if (elementOrNames instanceof HTMLElement) {\r\n element = elementOrNames;\r\n varNames = names ?? [];\r\n } else {\r\n element = document.documentElement;\r\n varNames = elementOrNames;\r\n }\r\n\r\n if (!element) return;\r\n varNames.forEach((name) => {\r\n element.style.removeProperty(normalizeVarName(name));\r\n });\r\n}\r\n\r\n// ============================================================\r\n// 高级功能\r\n// ============================================================\r\n\r\n/**\r\n * 检查元素是否有指定的 CSS 变量\r\n *\r\n * @param element - 目标元素(默认为 document.documentElement)\r\n * @param name - 变量名\r\n * @returns 如果变量存在则返回 true\r\n * @example\r\n * ```ts\r\n * if (hasCSSVar('--primary-color')) {\r\n * // 变量存在\r\n * }\r\n * ```\r\n */\r\nexport function hasCSSVar(name: string): boolean;\r\nexport function hasCSSVar(element: HTMLElement, name: string): boolean;\r\nexport function hasCSSVar(elementOrName: HTMLElement | string, name?: string): boolean {\r\n let element: HTMLElement;\r\n let varName: string;\r\n\r\n if (typeof elementOrName === 'string') {\r\n element = document.documentElement;\r\n varName = normalizeVarName(elementOrName);\r\n } else {\r\n element = elementOrName;\r\n varName = normalizeVarName(name as string);\r\n }\r\n\r\n if (!element) return false;\r\n\r\n // 检查内联样式\r\n if (element.style.getPropertyValue(varName)) return true;\r\n\r\n // 检查计算样式\r\n const computedStyle = window.getComputedStyle(element);\r\n return !!computedStyle.getPropertyValue(varName).trim();\r\n}\r\n\r\n/**\r\n * 获取元素上定义的所有 CSS 变量\r\n *\r\n * 注意:此方法通过遍历 computedStyle 的所有属性来查找 CSS 变量,\r\n * 在属性数量较多的元素上可能存在性能开销。\r\n * computedStyle.length 通常在数百到数千之间,遍历是 O(n) 操作。\r\n * 建议仅在调试或初始化时调用,避免在热路径中频繁使用。\r\n *\r\n * @param element - 目标元素(默认为 document.documentElement)\r\n * @returns CSS 变量键值对\r\n * @example\r\n * ```ts\r\n * const vars = getAllCSSVars()\r\n * // { '--primary-color': '#007bff', '--font-size': '16px', ... }\r\n * ```\r\n */\r\nexport function getAllCSSVars(element?: HTMLElement): Record<string, string> {\r\n const el = element ?? document.documentElement;\r\n if (!el) return {};\r\n\r\n const result: Record<string, string> = {};\r\n const computedStyle = window.getComputedStyle(el);\r\n\r\n // 遍历所有计算样式属性\r\n for (let i = 0; i < computedStyle.length; i++) {\r\n const prop = computedStyle[i] as string;\r\n if (prop.startsWith('--')) {\r\n const value = computedStyle.getPropertyValue(prop).trim();\r\n if (value) {\r\n result[prop] = value;\r\n }\r\n }\r\n }\r\n\r\n return result;\r\n}\r\n\r\n/**\r\n * 切换 CSS 变量的值(在两个值之间切换)\r\n *\r\n * @param element - 目标元素(默认为 document.documentElement)\r\n * @param name - 变量名\r\n * @param value1 - 第一个值\r\n * @param value2 - 第二个值\r\n * @returns 切换后的值\r\n * @example\r\n * ```ts\r\n * // 在 'dark' 和 'light' 之间切换主题\r\n * toggleCSSVar('--theme', 'dark', 'light')\r\n * ```\r\n */\r\nexport function toggleCSSVar(name: string, value1: string, value2: string): string;\r\nexport function toggleCSSVar(\r\n element: HTMLElement,\r\n name: string,\r\n value1: string,\r\n value2: string,\r\n): string;\r\nexport function toggleCSSVar(\r\n elementOrName: HTMLElement | string,\r\n nameOrValue1: string,\r\n value1OrValue2?: string,\r\n value2?: string,\r\n): string {\r\n let element: HTMLElement;\r\n let varName: string;\r\n let val1: string;\r\n let val2: string;\r\n\r\n if (typeof elementOrName === 'string') {\r\n element = document.documentElement;\r\n varName = normalizeVarName(elementOrName);\r\n val1 = nameOrValue1;\r\n val2 = value1OrValue2 as string;\r\n } else {\r\n element = elementOrName;\r\n varName = normalizeVarName(nameOrValue1);\r\n val1 = value1OrValue2 as string;\r\n val2 = value2 as string;\r\n }\r\n\r\n const currentValue = getCSSVar(element, varName);\r\n const newValue = currentValue === val1 ? val2 : val1;\r\n setCSSVar(element, varName, newValue);\r\n return newValue;\r\n}\r\n\r\n// ============================================================\r\n// CSS 变量观察器\r\n// ============================================================\r\n\r\n/**\r\n * CSS 变量观察器\r\n * 用于监听 CSS 变量的变化\r\n */\r\nexport class CSSVarObserver {\r\n private observer: MutationObserver | null = null;\r\n private callbacks = new Map<string, Set<CSSVarChangeCallback>>();\r\n private element: HTMLElement;\r\n\r\n constructor(element?: HTMLElement) {\r\n this.element = element ?? document.documentElement;\r\n }\r\n\r\n /**\r\n * 开始观察 CSS 变量变化\r\n *\r\n * @param names - 要观察的变量名数组(可选,不指定则观察所有)\r\n */\r\n observe(names?: string[]): void {\r\n if (this.observer) return;\r\n\r\n const targetNames = names?.map(normalizeVarName);\r\n\r\n this.observer = new MutationObserver((mutations) => {\r\n mutations.forEach((mutation) => {\r\n if (mutation.type === 'attributes' && mutation.attributeName === 'style') {\r\n this.checkChanges(targetNames);\r\n }\r\n });\r\n });\r\n\r\n this.observer.observe(this.element, {\r\n attributes: true,\r\n attributeFilter: ['style'],\r\n });\r\n }\r\n\r\n /**\r\n * 停止观察\r\n */\r\n disconnect(): void {\r\n this.observer?.disconnect();\r\n this.observer = null;\r\n }\r\n\r\n /**\r\n * 订阅变量变化\r\n *\r\n * @param name - 变量名\r\n * @param callback - 变化回调\r\n * @returns 取消订阅函数\r\n */\r\n subscribe(name: string, callback: CSSVarChangeCallback): () => void {\r\n const varName = normalizeVarName(name);\r\n\r\n if (!this.callbacks.has(varName)) {\r\n this.callbacks.set(varName, new Set());\r\n }\r\n\r\n this.callbacks.get(varName)!.add(callback);\r\n\r\n return () => {\r\n this.callbacks.get(varName)?.delete(callback);\r\n };\r\n }\r\n\r\n /**\r\n * 检查变量变化\r\n * FIX: P2-v11-37 添加最大条目限制,防止 lastValues Map 无限增长\r\n */\r\n private lastValues = new Map<string, string | null>();\r\n /** lastValues 最大条目数 */\r\n private static readonly MAX_LAST_VALUES_SIZE = 500;\r\n\r\n private checkChanges(targetNames?: string[]): void {\r\n const namesToCheck = targetNames ?? Array.from(this.callbacks.keys());\r\n\r\n // FIX: P2-v11-37 当 lastValues 超过最大条目数时,\r\n // 清理不在当前观察列表中的条目,防止内存泄漏\r\n if (this.lastValues.size > CSSVarObserver.MAX_LAST_VALUES_SIZE) {\r\n const activeNames = new Set(this.callbacks.keys());\r\n for (const key of this.lastValues.keys()) {\r\n if (!activeNames.has(key)) {\r\n this.lastValues.delete(key);\r\n }\r\n }\r\n }\r\n\r\n namesToCheck.forEach((name) => {\r\n const currentValue = getCSSVar(this.element, name);\r\n const lastValue = this.lastValues.get(name);\r\n\r\n if (currentValue !== lastValue) {\r\n this.lastValues.set(name, currentValue);\r\n\r\n const callbacks = this.callbacks.get(name);\r\n if (callbacks) {\r\n callbacks.forEach((cb) => cb(currentValue, lastValue ?? null, name));\r\n }\r\n }\r\n });\r\n }\r\n}\r\n\r\n// ============================================================\r\n// 主题管理\r\n// ============================================================\r\n\r\n/**\r\n * 主题配置\r\n */\r\nexport interface ThemeConfig {\r\n [key: string]: CSSVarValue;\r\n}\r\n\r\n/**\r\n * 主题管理器\r\n * 用于管理多主题切换\r\n */\r\nexport class ThemeManager {\r\n private themes = new Map<string, ThemeConfig>();\r\n private currentTheme: string | null = null;\r\n private element: HTMLElement;\r\n\r\n constructor(element?: HTMLElement) {\r\n this.element = element ?? document.documentElement;\r\n }\r\n\r\n /**\r\n * 注册主题\r\n *\r\n * @param name - 主题名称\r\n * @param config - 主题配置(CSS 变量键值对)\r\n */\r\n register(name: string, config: ThemeConfig): void {\r\n this.themes.set(name, config);\r\n }\r\n\r\n /**\r\n * 应用主题\r\n *\r\n * @param name - 主题名称\r\n */\r\n apply(name: string): boolean {\r\n const theme = this.themes.get(name);\r\n if (!theme) return false;\r\n\r\n setCSSVars(this.element, theme);\r\n this.currentTheme = name;\r\n\r\n // 设置 data-theme 属性\r\n this.element.setAttribute('data-theme', name);\r\n\r\n return true;\r\n }\r\n\r\n /**\r\n * 获取当前主题名称\r\n */\r\n getCurrentTheme(): string | null {\r\n return this.currentTheme;\r\n }\r\n\r\n /**\r\n * 获取已注册的主题列表\r\n */\r\n getRegisteredThemes(): string[] {\r\n return Array.from(this.themes.keys());\r\n }\r\n\r\n /**\r\n * 检查主题是否存在\r\n */\r\n hasTheme(name: string): boolean {\r\n return this.themes.has(name);\r\n }\r\n\r\n /**\r\n * 获取主题配置\r\n */\r\n getThemeConfig(name: string): ThemeConfig | undefined {\r\n return this.themes.get(name);\r\n }\r\n}\r\n\r\n// ============================================================\r\n// 导出 - FIX: DTS build error - 删除重复导出(已在 index.ts 中导出)\r\n// ============================================================\r\n","/**\r\n * @lytjs/web - ResizeObserver 管理模块\r\n *\r\n * 提供 ResizeObserver 的安全封装,确保在组件卸载时自动清理观察者,\r\n * 防止内存泄漏。\r\n * FIX: P2-5 ResizeObserver 未清理问题\r\n *\r\n * @module @lytjs/web/resize-observer\r\n * @version 6.0.0\r\n */\r\n\r\n// ============================================================\r\n// 类型定义\r\n// ============================================================\r\n\r\n/**\r\n * ResizeObserver 回调函数类型\r\n */\r\nexport type ResizeObserverCallback = (entries: ResizeObserverEntry[]) => void;\r\n\r\n/**\r\n * ResizeObserver 观察选项\r\n */\r\nexport interface ResizeObserverOptions {\r\n /** 指定要观察的盒模型 */\r\n box?: 'content-box' | 'border-box' | 'device-pixel-content-box';\r\n}\r\n\r\n// ============================================================\r\n// ResizeObserver 管理器\r\n// ============================================================\r\n\r\n/**\r\n * 受管理的 ResizeObserver 包装类\r\n *\r\n * 自动处理 ResizeObserver 的创建、观察和清理,\r\n * 确保在组件卸载时不会泄漏观察者。\r\n *\r\n * FIX: P2-5 ResizeObserver 未清理问题\r\n *\r\n * @example\r\n * ```ts\r\n * // 创建管理器\r\n * const manager = new ResizeObserverManager((entries) => {\r\n * for (const entry of entries) {\r\n * console.log('Element resized:', entry.target);\r\n * }\r\n * });\r\n *\r\n * // 观察元素\r\n * manager.observe(myElement);\r\n *\r\n * // 组件卸载时清理\r\n * onUnmounted(() => {\r\n * manager.disconnect();\r\n * });\r\n * ```\r\n */\r\nexport class ResizeObserverManager {\r\n private observer: ResizeObserver | null = null;\r\n private callback: ResizeObserverCallback;\r\n private observedElements = new Set<Element>();\r\n private isConnected = false;\r\n\r\n constructor(callback: ResizeObserverCallback) {\r\n this.callback = callback;\r\n\r\n // 检查浏览器支持\r\n if (typeof ResizeObserver === 'undefined') {\r\n if (__DEV__) {\r\n console.warn(\r\n '[lytjs/resize-observer] ResizeObserver is not supported in this environment.',\r\n );\r\n }\r\n return;\r\n }\r\n\r\n // 创建 ResizeObserver 实例\r\n this.observer = new ResizeObserver((entries) => {\r\n // 过滤掉已停止观察的条目\r\n const activeEntries = entries.filter((entry) => this.observedElements.has(entry.target));\r\n if (activeEntries.length > 0) {\r\n this.callback(activeEntries);\r\n }\r\n });\r\n }\r\n\r\n /**\r\n * 开始观察元素\r\n *\r\n * @param target - 要观察的目标元素\r\n * @param options - 观察选项\r\n * @returns 是否成功开始观察\r\n */\r\n observe(target: Element, options?: ResizeObserverOptions): boolean {\r\n if (!this.observer) {\r\n if (__DEV__) {\r\n console.warn('[lytjs/resize-observer] Cannot observe: ResizeObserver is not available.');\r\n }\r\n return false;\r\n }\r\n\r\n // 避免重复观察同一元素\r\n if (this.observedElements.has(target)) {\r\n if (__DEV__) {\r\n console.warn('[lytjs/resize-observer] Element is already being observed.');\r\n }\r\n return false;\r\n }\r\n\r\n try {\r\n this.observer.observe(target, options);\r\n this.observedElements.add(target);\r\n this.isConnected = true;\r\n return true;\r\n } catch (err) {\r\n if (__DEV__) {\r\n console.error('[lytjs/resize-observer] Error observing element:', err);\r\n }\r\n return false;\r\n }\r\n }\r\n\r\n /**\r\n * 停止观察指定元素\r\n *\r\n * @param target - 要停止观察的目标元素\r\n * @returns 是否成功停止观察\r\n */\r\n unobserve(target: Element): boolean {\r\n if (!this.observer) {\r\n return false;\r\n }\r\n\r\n if (!this.observedElements.has(target)) {\r\n return false;\r\n }\r\n\r\n try {\r\n this.observer.unobserve(target);\r\n this.observedElements.delete(target);\r\n\r\n // 如果没有观察的元素了,标记为断开连接\r\n if (this.observedElements.size === 0) {\r\n this.isConnected = false;\r\n }\r\n return true;\r\n } catch (err) {\r\n if (__DEV__) {\r\n console.error('[lytjs/resize-observer] Error unobserving element:', err);\r\n }\r\n return false;\r\n }\r\n }\r\n\r\n /**\r\n * 停止观察所有元素并断开连接\r\n *\r\n * FIX: P2-5 这是关键方法,确保在组件卸载时调用此方法\r\n */\r\n disconnect(): void {\r\n if (!this.observer) {\r\n return;\r\n }\r\n\r\n try {\r\n this.observer.disconnect();\r\n this.observedElements.clear();\r\n this.isConnected = false;\r\n } catch (err) {\r\n if (__DEV__) {\r\n console.error('[lytjs/resize-observer] Error disconnecting observer:', err);\r\n }\r\n }\r\n }\r\n\r\n /**\r\n * 检查是否正在观察指定元素\r\n *\r\n * @param target - 要检查的目标元素\r\n * @returns 是否正在观察\r\n */\r\n isObserving(target: Element): boolean {\r\n return this.observedElements.has(target);\r\n }\r\n\r\n /**\r\n * 获取当前观察的元素数量\r\n */\r\n get observedCount(): number {\r\n return this.observedElements.size;\r\n }\r\n\r\n /**\r\n * 检查观察者是否已连接(正在观察至少一个元素)\r\n */\r\n get connected(): boolean {\r\n return this.isConnected;\r\n }\r\n\r\n /**\r\n * 检查 ResizeObserver 是否可用\r\n */\r\n get isAvailable(): boolean {\r\n return this.observer !== null;\r\n }\r\n}\r\n\r\n// ============================================================\r\n// 便捷函数\r\n// ============================================================\r\n\r\n/**\r\n * 创建并使用 ResizeObserver,返回清理函数\r\n *\r\n * 这是使用 ResizeObserver 的推荐方式,确保在组件卸载时调用返回的清理函数。\r\n *\r\n * FIX: P2-5 ResizeObserver 未清理问题\r\n *\r\n * @example\r\n * ```ts\r\n * // 在组件中使用\r\n * const cleanup = useResizeObserver(myElement, (entries) => {\r\n * for (const entry of entries) {\r\n * console.log('Resized:', entry.contentRect);\r\n * }\r\n * });\r\n *\r\n * // 组件卸载时清理\r\n * onUnmounted(() => {\r\n * cleanup();\r\n * });\r\n * ```\r\n *\r\n * @param target - 要观察的目标元素\r\n * @param callback - 尺寸变化回调\r\n * @param options - 观察选项\r\n * @returns 清理函数,调用后停止观察并释放资源\r\n */\r\nexport function useResizeObserver(\r\n target: Element,\r\n callback: ResizeObserverCallback,\r\n options?: ResizeObserverOptions,\r\n): () => void {\r\n const manager = new ResizeObserverManager(callback);\r\n manager.observe(target, options);\r\n\r\n // 返回清理函数\r\n return () => {\r\n manager.disconnect();\r\n };\r\n}\r\n\r\n/**\r\n * 检查浏览器是否支持 ResizeObserver\r\n *\r\n * @returns 如果支持则返回 true\r\n */\r\nexport function supportsResizeObserver(): boolean {\r\n return typeof ResizeObserver !== 'undefined';\r\n}\r\n\r\n// ============================================================\r\n// 全局 ResizeObserver 注册表(用于调试和监控)\r\n// ============================================================\r\n\r\n/**\r\n * ResizeObserver 统计信息\r\n */\r\nexport interface ResizeObserverStats {\r\n /** 活跃的管理器数量 */\r\n activeManagers: number;\r\n /** 总共观察的元素数量 */\r\n totalObservedElements: number;\r\n}\r\n\r\n// 开发模式下导出统计信息\r\nif (__DEV__) {\r\n // 用于跟踪所有创建的 ResizeObserverManager 实例\r\n const managerRegistry = new WeakSet<ResizeObserverManager>();\r\n\r\n // 重写构造函数以跟踪实例\r\n const OriginalManager = ResizeObserverManager;\r\n (ResizeObserverManager as unknown as typeof ResizeObserverManager & {\r\n new (callback: ResizeObserverCallback): ResizeObserverManager;\r\n }) = class extends OriginalManager {\r\n constructor(callback: ResizeObserverCallback) {\r\n super(callback);\r\n managerRegistry.add(this);\r\n }\r\n };\r\n\r\n /**\r\n * 获取 ResizeObserver 统计信息(仅开发模式)\r\n */\r\n (globalThis as Record<string, unknown>).__getResizeObserverStats = (): ResizeObserverStats => {\r\n // 注意:WeakSet 无法遍历,这里仅作为示例\r\n return {\r\n activeManagers: 0,\r\n totalObservedElements: 0,\r\n };\r\n };\r\n}\r\n"]}
package/package.json ADDED
@@ -0,0 +1,60 @@
1
+ {
2
+ "$schema": "https://json.schemastore.org/package.json",
3
+ "name": "@lytjs/web",
4
+ "version": "6.4.0",
5
+ "description": "LytJS web platform utilities - CSS variables and web-specific features",
6
+ "author": "lytjs",
7
+ "license": "MIT",
8
+ "type": "module",
9
+ "main": "./dist/index.cjs",
10
+ "module": "./dist/index.mjs",
11
+ "types": "./dist/index.d.ts",
12
+ "exports": {
13
+ ".": {
14
+ "types": "./dist/index.d.ts",
15
+ "import": "./dist/index.mjs",
16
+ "require": "./dist/index.cjs"
17
+ },
18
+ "./package.json": "./package.json"
19
+ },
20
+ "files": [
21
+ "dist",
22
+ "README.md"
23
+ ],
24
+ "sideEffects": false,
25
+ "scripts": {
26
+ "dev": "tsup --watch",
27
+ "build": "tsup",
28
+ "test": "vitest run",
29
+ "test:watch": "vitest",
30
+ "test:coverage": "vitest run --coverage",
31
+ "type-check": "tsc --noEmit",
32
+ "clean": "rm -rf dist node_modules .turbo"
33
+ },
34
+ "dependencies": {},
35
+ "devDependencies": {
36
+ "tsup": "^8.3.6",
37
+ "typescript": "^5.7.3",
38
+ "vitest": "^3.0.0"
39
+ },
40
+ "peerDependencies": {},
41
+ "publishConfig": {
42
+ "access": "public",
43
+ "registry": "https://registry.npmjs.org/"
44
+ },
45
+ "repository": {
46
+ "type": "git",
47
+ "url": "https://gitee.com/lytjs/lytjs.git",
48
+ "directory": "packages/web"
49
+ },
50
+ "keywords": [
51
+ "lytjs",
52
+ "web",
53
+ "css-variables",
54
+ "theme"
55
+ ],
56
+ "homepage": "https://gitee.com/lytjs/lytjs/tree/develop/packages/web#readme",
57
+ "bugs": {
58
+ "url": "https://gitee.com/lytjs/lytjs/issues"
59
+ }
60
+ }