@mantou/gem 1.7.0 → 1.7.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.
Files changed (98) hide show
  1. package/dist/gem.es.js +402 -543
  2. package/dist/gem.umd.js +27 -33
  3. package/elements/base/dialog.d.ts +9 -7
  4. package/elements/base/dialog.d.ts.map +1 -1
  5. package/elements/base/dialog.js +12 -3
  6. package/elements/base/dialog.js.map +1 -1
  7. package/elements/base/gesture.d.ts +4 -13
  8. package/elements/base/gesture.d.ts.map +1 -1
  9. package/elements/base/gesture.js +152 -135
  10. package/elements/base/gesture.js.map +1 -1
  11. package/elements/base/link.d.ts +12 -9
  12. package/elements/base/link.d.ts.map +1 -1
  13. package/elements/base/link.js +81 -62
  14. package/elements/base/link.js.map +1 -1
  15. package/elements/base/modal-factory.d.ts +104 -80
  16. package/elements/base/modal-factory.d.ts.map +1 -1
  17. package/elements/base/modal-factory.js +12 -8
  18. package/elements/base/modal-factory.js.map +1 -1
  19. package/elements/base/reflect.js.map +1 -1
  20. package/elements/base/route.d.ts +12 -5
  21. package/elements/base/route.d.ts.map +1 -1
  22. package/elements/base/route.js +17 -5
  23. package/elements/base/route.js.map +1 -1
  24. package/elements/base/title.d.ts +3 -1
  25. package/elements/base/title.d.ts.map +1 -1
  26. package/elements/base/title.js +14 -16
  27. package/elements/base/title.js.map +1 -1
  28. package/elements/base/unsafe.js +1 -1
  29. package/elements/base/unsafe.js.map +1 -1
  30. package/elements/base/use.d.ts +1 -1
  31. package/elements/base/use.d.ts.map +1 -1
  32. package/elements/base/use.js +28 -20
  33. package/elements/base/use.js.map +1 -1
  34. package/helper/i18n.d.ts +4 -4
  35. package/helper/i18n.d.ts.map +1 -1
  36. package/helper/i18n.js.map +1 -1
  37. package/helper/mediaquery.d.ts +16 -18
  38. package/helper/mediaquery.d.ts.map +1 -1
  39. package/helper/mediaquery.js +42 -41
  40. package/helper/mediaquery.js.map +1 -1
  41. package/helper/request.d.ts +1 -1
  42. package/helper/request.d.ts.map +1 -1
  43. package/helper/request.js.map +1 -1
  44. package/helper/ssr-shim.d.ts +2 -0
  45. package/helper/ssr-shim.d.ts.map +1 -0
  46. package/helper/ssr-shim.js +29 -0
  47. package/helper/ssr-shim.js.map +1 -0
  48. package/helper/theme.d.ts +2 -2
  49. package/helper/theme.d.ts.map +1 -1
  50. package/helper/theme.js +20 -24
  51. package/helper/theme.js.map +1 -1
  52. package/index.d.ts +0 -10
  53. package/index.d.ts.map +1 -1
  54. package/index.js +0 -7
  55. package/index.js.map +1 -1
  56. package/lib/decorators.d.ts +4 -4
  57. package/lib/decorators.d.ts.map +1 -1
  58. package/lib/decorators.js +1 -2
  59. package/lib/decorators.js.map +1 -1
  60. package/lib/element.d.ts +16 -10
  61. package/lib/element.d.ts.map +1 -1
  62. package/lib/element.js +57 -79
  63. package/lib/element.js.map +1 -1
  64. package/lib/history.d.ts +1 -1
  65. package/lib/history.d.ts.map +1 -1
  66. package/lib/history.js +2 -2
  67. package/lib/history.js.map +1 -1
  68. package/lib/store.d.ts +2 -2
  69. package/lib/store.d.ts.map +1 -1
  70. package/lib/store.js.map +1 -1
  71. package/lib/utils.d.ts +8 -32
  72. package/lib/utils.d.ts.map +1 -1
  73. package/lib/utils.js +6 -21
  74. package/lib/utils.js.map +1 -1
  75. package/lib/version.d.ts +1 -1
  76. package/lib/version.js +1 -1
  77. package/package.json +2 -2
  78. package/src/elements/base/dialog.ts +10 -3
  79. package/src/elements/base/gesture.ts +52 -46
  80. package/src/elements/base/link.ts +69 -61
  81. package/src/elements/base/modal-factory.ts +5 -0
  82. package/src/elements/base/route.ts +22 -5
  83. package/src/elements/base/title.ts +8 -11
  84. package/src/elements/base/unsafe.ts +1 -1
  85. package/src/elements/base/use.ts +4 -6
  86. package/src/helper/i18n.ts +3 -3
  87. package/src/helper/mediaquery.ts +43 -42
  88. package/src/helper/ssr-shim.ts +29 -0
  89. package/src/helper/theme.ts +22 -24
  90. package/src/index.ts +0 -16
  91. package/src/lib/decorators.ts +1 -2
  92. package/src/lib/element.ts +56 -71
  93. package/src/lib/history.ts +2 -1
  94. package/src/lib/utils.ts +10 -42
  95. package/src/lib/version.ts +1 -1
  96. package/src/test/gem-element/decorators.test.ts +6 -6
  97. package/src/test/history.test.ts +3 -1
  98. package/src/test/utils.test.ts +8 -1
@@ -13,8 +13,9 @@ import {
13
13
  kebabToCamelCase,
14
14
  PropProxyMap,
15
15
  removeItems,
16
- useNativeCSSStyleSheet,
17
16
  } from './utils';
17
+ import * as GemExports from './element';
18
+ import * as VersionExports from './version';
18
19
 
19
20
  export { html, svg, render, directive, TemplateResult, SVGTemplateResult } from 'lit-html';
20
21
  export { repeat } from 'lit-html/directives/repeat';
@@ -27,19 +28,15 @@ export { ifDefined } from 'lit-html/directives/if-defined';
27
28
  declare global {
28
29
  interface ElementInternals extends ARIAMixin {
29
30
  // https://developer.mozilla.org/en-US/docs/Web/API/CustomStateSet
30
- states?: Set<string>;
31
- // https://w3c.github.io/aria/#role_definitions
32
- role?: string;
31
+ states: Set<string>;
33
32
  }
34
33
  // 用于 css 选择器选择元素,使用 @refobject 自动选择获取
35
34
  // 必须使用 attr 赋值
36
35
  /**
37
36
  * @attr ref
38
- * @attr inert
39
37
  */
40
38
  interface HTMLElement {
41
- attachInternals: () => ElementInternals;
42
- inert: boolean;
39
+ ref: string;
43
40
  }
44
41
  }
45
42
 
@@ -81,10 +78,16 @@ const updateSymbol = Symbol('update');
81
78
  export interface GemElementOptions {
82
79
  isLight?: boolean;
83
80
  isAsync?: boolean;
81
+ // https://developer.mozilla.org/en-US/docs/Web/API/Element/attachShadow#options
84
82
  delegatesFocus?: boolean;
83
+ slotAssignment?: 'named' | 'manual';
85
84
  }
86
85
 
87
86
  export abstract class GemElement<T = Record<string, unknown>> extends HTMLElement {
87
+ // 禁止覆盖自定义元素原生生命周期方法
88
+ // https://github.com/microsoft/TypeScript/issues/21388#issuecomment-934345226
89
+ static #final = Symbol();
90
+
88
91
  // 这里只是字段申明,不能赋值,否则子类会继承被共享该字段
89
92
  static observedAttributes?: string[]; // WebAPI 中是实时检查这个列表
90
93
  static booleanAttributes?: Set<string>;
@@ -114,21 +117,21 @@ export abstract class GemElement<T = Record<string, unknown>> extends HTMLElemen
114
117
  #memoList?: EffectItem<any>[];
115
118
  #unmountCallback?: any;
116
119
 
117
- constructor({ isAsync, isLight, delegatesFocus }: GemElementOptions = {}) {
120
+ constructor({ isAsync, isLight, delegatesFocus, slotAssignment }: GemElementOptions = {}) {
118
121
  super();
119
- (this as any)[constructorSymbol] = true;
120
122
 
121
123
  // 外部不可见,但允许类外面使用
122
- addMicrotask(() => ((this as any)[initSymbol] = false));
123
- (this as any)[initSymbol] = true;
124
- (this as any)[updateSymbol] = () => {
124
+ addMicrotask(() => Reflect.set(this, initSymbol, false));
125
+ Reflect.set(this, constructorSymbol, true);
126
+ Reflect.set(this, initSymbol, true);
127
+ Reflect.set(this, updateSymbol, () => {
125
128
  if (this.#isMounted) {
126
129
  addMicrotask(this.#update);
127
130
  }
128
- };
131
+ });
129
132
 
130
133
  this.#isAsync = isAsync;
131
- this.#renderRoot = isLight ? this : this.attachShadow({ mode: 'open', delegatesFocus });
134
+ this.#renderRoot = isLight ? this : this.attachShadow({ mode: 'open', delegatesFocus, slotAssignment });
132
135
 
133
136
  const { adoptedStyleSheets } = new.target;
134
137
  if (adoptedStyleSheets) {
@@ -139,34 +142,10 @@ export abstract class GemElement<T = Record<string, unknown>> extends HTMLElemen
139
142
  this.effect(
140
143
  () => {
141
144
  const root = this.getRootNode() as ShadowRoot | Document;
142
- if (!useNativeCSSStyleSheet) {
143
- const ele: any = root === document ? document.body : root;
144
- ele._sheets = ele._sheets || {};
145
- sheets.forEach(({ style, media }: any) => {
146
- if (ele._sheets[style]) {
147
- ele._sheets[style].count++;
148
- } else {
149
- const s = document.createElement('style');
150
- s.innerHTML = style;
151
- s.media = media.mediaText;
152
- ele.append(s);
153
- ele._sheets[style] = { ele: s, count: 1 };
154
- }
155
- });
156
- return () => {
157
- sheets.forEach(({ style }: any) => {
158
- ele._sheets[style].count--;
159
- if (!ele._sheets[style].count) {
160
- delete ele._sheets[style];
161
- }
162
- });
163
- };
164
- } else {
165
- root.adoptedStyleSheets = [...root.adoptedStyleSheets, ...sheets];
166
- return () => {
167
- root.adoptedStyleSheets = removeItems(root.adoptedStyleSheets, sheets);
168
- };
169
- }
145
+ root.adoptedStyleSheets = [...root.adoptedStyleSheets, ...sheets];
146
+ return () => {
147
+ root.adoptedStyleSheets = removeItems(root.adoptedStyleSheets, sheets);
148
+ };
170
149
  },
171
150
  () => [],
172
151
  );
@@ -178,16 +157,18 @@ export abstract class GemElement<T = Record<string, unknown>> extends HTMLElemen
178
157
  if (!this.#internals) {
179
158
  this.#internals = this.attachInternals();
180
159
  // https://groups.google.com/a/chromium.org/g/blink-dev/c/JvpHoUfhJYE?pli=1
160
+ // https://bugs.webkit.org/show_bug.cgi?id=215911
161
+ // https://bugzilla.mozilla.org/show_bug.cgi?id=1588763
181
162
  try {
182
- this.#internals.states?.add('foo');
183
- this.#internals.states?.delete('foo');
163
+ this.#internals.states.add('foo');
164
+ this.#internals.states.delete('foo');
184
165
  } catch {
185
166
  Reflect.defineProperty(this.#internals, 'states', {
186
- value: new Proxy(this.#internals.states!, {
187
- get(target: any, p) {
188
- return (str: string) => target[p](`--${str}`);
189
- },
190
- }),
167
+ value: {
168
+ has: (v: string) => kebabToCamelCase(v) in this.dataset,
169
+ add: (v: string) => (this.dataset[kebabToCamelCase(v)] = ''),
170
+ delete: (v: string) => delete this.dataset[kebabToCamelCase(v)],
171
+ },
191
172
  });
192
173
  }
193
174
  }
@@ -315,21 +296,8 @@ export abstract class GemElement<T = Record<string, unknown>> extends HTMLElemen
315
296
 
316
297
  #render = () => {
317
298
  this.#execMemo();
318
- const styles = useNativeCSSStyleSheet
319
- ? ''
320
- : html`${this.shadowRoot?.adoptedStyleSheets?.map(
321
- (e: any) =>
322
- html`
323
- <style media=${e.media.mediaText}>
324
- ${e.style}
325
- </style>
326
- `,
327
- )}`;
328
- if (this.render) {
329
- const r = this.render();
330
- return r && html`${r}${styles}`;
331
- }
332
- return this.#renderRoot === this ? undefined : html`<slot></slot>${styles}`;
299
+ if (this.render) return this.render();
300
+ return this.#renderRoot === this ? undefined : html`<slot></slot>`;
333
301
  };
334
302
 
335
303
  /**@lifecycle */
@@ -388,15 +356,18 @@ export abstract class GemElement<T = Record<string, unknown>> extends HTMLElemen
388
356
  if (this.#isMounted) {
389
357
  addMicrotask(this.#update);
390
358
  }
359
+ return GemElement.#final;
391
360
  }
392
361
 
393
362
  #connectedCallback = () => {
394
- // 似乎这是最早的判断不在 `constructor` 中的地方
395
- (this as any)[constructorSymbol] = false;
396
363
  if (this.#isAppendReason) {
397
364
  this.#isAppendReason = false;
398
365
  return;
399
366
  }
367
+
368
+ // 似乎这是最早的判断不在 `constructor` 中的地方
369
+ Reflect.set(this, constructorSymbol, false);
370
+
400
371
  this.willMount?.();
401
372
  const { observedStores, rootElement } = this.constructor as typeof GemElement;
402
373
  observedStores?.forEach((store) => {
@@ -443,13 +414,16 @@ export abstract class GemElement<T = Record<string, unknown>> extends HTMLElemen
443
414
  } else {
444
415
  this.#connectedCallback();
445
416
  }
417
+ return GemElement.#final;
446
418
  }
447
419
 
448
420
  /**
449
421
  * @private
450
422
  * @final
451
423
  */
452
- // adoptedCallback() {}
424
+ adoptedCallback() {
425
+ return GemElement.#final;
426
+ }
453
427
 
454
428
  /**
455
429
  * @private
@@ -473,6 +447,7 @@ export abstract class GemElement<T = Record<string, unknown>> extends HTMLElemen
473
447
  });
474
448
  this.#effectList = this.#effectList?.filter(({ inConstructor }) => inConstructor);
475
449
  this.#memoList = this.#memoList?.filter(({ inConstructor }) => inConstructor);
450
+ return GemElement.#final;
476
451
  }
477
452
  }
478
453
 
@@ -499,7 +474,7 @@ export function defineAttribute(target: GemElement, prop: string, attr: string)
499
474
  },
500
475
  set(v: string | null | undefined | number | boolean) {
501
476
  const that = this as GemElement;
502
- const proxy = gemElementProxyMap.get(this) as any;
477
+ const proxy = gemElementProxyMap.get(this);
503
478
  const hasSet = proxy[prop];
504
479
  const value = that.getAttribute(attr);
505
480
  // https://github.com/whatwg/dom/issues/922
@@ -540,7 +515,7 @@ export function defineProperty(
540
515
  },
541
516
  set(v) {
542
517
  const that = this as GemElement;
543
- const proxy = gemElementProxyMap.get(that) as any;
518
+ const proxy = gemElementProxyMap.get(that);
544
519
  if (v !== proxy[prop]) {
545
520
  if (event) {
546
521
  proxy[prop] = v?.[isEventHandleSymbol]
@@ -550,7 +525,7 @@ export function defineProperty(
550
525
  that.dispatchEvent(evt);
551
526
  v(detail, options);
552
527
  };
553
- proxy[prop][isEventHandleSymbol] = true;
528
+ Reflect.set(proxy[prop]!, isEventHandleSymbol, true);
554
529
  // emitter 不触发元素更新
555
530
  } else {
556
531
  proxy[prop] = v;
@@ -623,5 +598,15 @@ customElements.define = (name: string, cls: CustomElementConstructor, options?:
623
598
  defineRefs?.forEach((ref) => defineRef(cls.prototype, kebabToCamelCase(ref), ref));
624
599
  }
625
600
 
626
- nativeDefineElement(name, cls as CustomElementConstructor, options);
601
+ nativeDefineElement(name, cls, options);
627
602
  };
603
+
604
+ declare global {
605
+ interface Window {
606
+ __GEM_DEVTOOLS__HOOK__?: (typeof GemExports & typeof VersionExports) | Record<string, never>;
607
+ }
608
+ }
609
+
610
+ if (window.__GEM_DEVTOOLS__HOOK__) {
611
+ Object.assign(window.__GEM_DEVTOOLS__HOOK__, { ...GemExports, ...VersionExports });
612
+ }
@@ -1,3 +1,5 @@
1
+ // https://github.com/WICG/navigation-api#stakeholder-feedback
2
+
1
3
  import { createStore, updateStore, connect } from './store';
2
4
  import { QueryString, cleanObject, GemError, absoluteLocation } from './utils';
3
5
 
@@ -38,7 +40,6 @@ export interface UpdateHistoryParams {
38
40
  // 实际应用值
39
41
  type HistoryParams = UpdateHistoryParams & { title: string; path: string; query: QueryString; hash: string };
40
42
 
41
- // TODO: WeakRef
42
43
  const paramsMap = new Map<string, HistoryParams>();
43
44
 
44
45
  function validData(data: any) {
package/src/lib/utils.ts CHANGED
@@ -23,7 +23,7 @@ function execMicrotaskStack() {
23
23
 
24
24
  /**
25
25
  * 添加回调函数到微任务队列栈;
26
- * 先进后执行;
26
+ * 先进后执行,使用这个函数可以改变嵌套的元素 `mounted` 的顺序;
27
27
  */
28
28
  export function addMicrotaskToStack(func: () => void) {
29
29
  if (!microtaskStack.length) {
@@ -50,8 +50,8 @@ interface LinkedListItem<T> {
50
50
  next?: LinkedListItem<T>;
51
51
  }
52
52
  // work on nodejs
53
- export class LinkedList<T = any> extends (globalThis.EventTarget || Object) {
54
- addEventListener: <K extends keyof LinkedListEventMap>(
53
+ export class LinkedList<T = any> extends EventTarget {
54
+ declare addEventListener: <K extends keyof LinkedListEventMap>(
55
55
  type: K,
56
56
  listener: (this: LinkedList<T>, ev: LinkedListEventMap[K]) => any,
57
57
  options?: boolean | AddEventListenerOptions,
@@ -131,11 +131,6 @@ export class PropProxyMap<T extends NonPrimitive, V = unknown> extends WeakMap<T
131
131
  }
132
132
  }
133
133
 
134
- declare global {
135
- interface URLSearchParams {
136
- entries(): Iterable<readonly [string | number | symbol, any]>;
137
- }
138
- }
139
134
  export class QueryString extends URLSearchParams {
140
135
  constructor(param?: any) {
141
136
  super(param);
@@ -216,22 +211,6 @@ export type Sheet<T> = {
216
211
  [P in keyof T]: P;
217
212
  } & { [SheetToken]: CSSStyleSheet };
218
213
 
219
- declare global {
220
- interface CSSStyleSheet {
221
- replaceSync: (str: string) => void;
222
- }
223
-
224
- interface CSSRuleList {
225
- item(index: number): CSSStyleRule;
226
- }
227
- interface ShadowRoot {
228
- adoptedStyleSheets: CSSStyleSheet[];
229
- }
230
- interface Document {
231
- adoptedStyleSheets: CSSStyleSheet[];
232
- }
233
- }
234
-
235
214
  export type StyledType = 'id' | 'class' | 'keyframes';
236
215
  export interface StyledValueObject {
237
216
  styledContent: string;
@@ -241,22 +220,6 @@ export interface StyledKeyValuePair {
241
220
  [key: string]: StyledValueObject;
242
221
  }
243
222
 
244
- // !!! 目前只有 Chrome/FirefoxNightly 支持
245
- // https://bugzilla.mozilla.org/show_bug.cgi?id=1520690
246
- // https://bugs.webkit.org/show_bug.cgi?id=228684
247
- export let useNativeCSSStyleSheet = true;
248
- let CSSStyleSheet = window.CSSStyleSheet;
249
- try {
250
- new (CSSStyleSheet as any)();
251
- } catch {
252
- useNativeCSSStyleSheet = false;
253
- CSSStyleSheet = class {
254
- media = { mediaText: '' };
255
- style = '';
256
- replaceSync = (style: string) => (this.style = style);
257
- } as any;
258
- }
259
-
260
223
  /**
261
224
  *
262
225
  * 创建 style sheet 用于 `adoptedStyleSheets`,不支持样式更新
@@ -293,6 +256,8 @@ export function randomStr(number = 5, origin = '0123456789abcdefghijklmnopqrstuv
293
256
  const nestingRuleRegExp = new RegExp('&.*{((.|\n)*)}', 'g');
294
257
  // 只支持一层嵌套
295
258
  // https://drafts.csswg.org/css-nesting-1/
259
+ // https://bugzilla.mozilla.org/show_bug.cgi?id=1648037
260
+ // https://bugs.webkit.org/show_bug.cgi?id=223497
296
261
  function flatStyled(style: string, type: StyledType): StyledValueObject {
297
262
  const nestingRules: string[] = [];
298
263
  let styledContent =
@@ -404,6 +369,9 @@ export function classMap(object: Record<string, boolean>) {
404
369
 
405
370
  export const partMap = classMap;
406
371
 
407
- export function exportPartsMap(object: Record<string, string | undefined>) {
408
- return objectMapToString(object, ',', (key, value) => (value !== undefined ? `${key}:${value}` : ''));
372
+ // https://developer.mozilla.org/en-US/docs/Web/HTML/Global_attributes/exportparts
373
+ export function exportPartsMap(object: Record<string, string | undefined | boolean>) {
374
+ return objectMapToString(object, ',', (key, value) =>
375
+ value === true || key === value ? key : value ? `${key}:${value}` : '',
376
+ );
409
377
  }
@@ -1 +1 @@
1
- export const version = '1.7.0';
1
+ export const version = '1.7.2';
@@ -38,7 +38,7 @@ class DecoratorGemElement extends GemElement {
38
38
  @attribute rankAttr: string;
39
39
  @boolattribute rankDisabled: boolean;
40
40
  @numattribute rankCount: number;
41
- @property dataProp = { value: '' };
41
+ @property propData = { value: '' };
42
42
  @state openState: boolean;
43
43
  @part headerPart: string;
44
44
  @refobject inputRef: RefObject<HTMLElement>;
@@ -46,8 +46,8 @@ class DecoratorGemElement extends GemElement {
46
46
  renderCount = 0;
47
47
  render() {
48
48
  this.renderCount++;
49
- const { rankAttr, rankDisabled, rankCount, dataProp } = this;
50
- return html`attr: ${rankAttr}, disabled: ${rankDisabled}, count: ${rankCount}, prop: ${dataProp.value}`;
49
+ const { rankAttr, rankDisabled, rankCount, propData } = this;
50
+ return html`attr: ${rankAttr}, disabled: ${rankDisabled}, count: ${rankCount}, prop: ${propData.value}`;
51
51
  }
52
52
  }
53
53
 
@@ -70,7 +70,7 @@ describe('装饰器', () => {
70
70
  const el: DecoratorGemElement = await fixture(html`
71
71
  <decorator-gem-demo
72
72
  @say-hi=${(e: CustomEvent) => (a = e.detail)}
73
- .dataProp=${{ value: 'prop' }}
73
+ .propData=${{ value: 'prop' }}
74
74
  rank-attr="attr"
75
75
  rank-disabled
76
76
  rank-count="2"
@@ -87,11 +87,11 @@ describe('装饰器', () => {
87
87
  expect(DecoratorGemElement.defineParts).to.eql(['header-part']);
88
88
  expect(DecoratorGemElement.defineSlots).to.eql(['body-slot']);
89
89
  expect(DecoratorGemElement.defineRefs?.[0].startsWith('input-ref-')).to.equal(true);
90
- expect(DecoratorGemElement.observedProperties).to.eql(['dataProp']);
90
+ expect(DecoratorGemElement.observedProperties).to.eql(['propData']);
91
91
  expect(el.rankAttr).to.equal('attr');
92
92
  expect(el.rankDisabled).to.equal(true);
93
93
  expect(el.rankCount).to.equal(2);
94
- expect(el.dataProp).to.eql({ value: 'prop' });
94
+ expect(el.propData).to.eql({ value: 'prop' });
95
95
  expect(el.openState).to.equal(false);
96
96
  expect(el.headerPart).to.equal('header-part');
97
97
  expect(el.inputRef.ref.startsWith('input-ref-')).to.equal(true);
@@ -6,11 +6,13 @@ describe('history 测试', () => {
6
6
  it('hash', async () => {
7
7
  const historyLength = window.history.length;
8
8
  const hash = window.location.hash;
9
+ // 等待浏览器就绪
10
+ await aTimeout(1000);
9
11
  history.push({ path: '/a', hash: '#a' });
10
12
  await aTimeout(10);
11
13
  expect(window.location.hash).to.equal('#a');
12
14
  history.back();
13
- await aTimeout(600);
15
+ await aTimeout(10);
14
16
  expect(window.location.hash).to.equal(hash);
15
17
  history.push({ path: '/a', hash: '#b' });
16
18
  await aTimeout(10);
@@ -14,6 +14,12 @@ import {
14
14
  absoluteLocation,
15
15
  } from '../lib/utils';
16
16
 
17
+ declare global {
18
+ interface CSSRuleList {
19
+ item(index: number): CSSStyleRule;
20
+ }
21
+ }
22
+
17
23
  describe('utils 测试', () => {
18
24
  it('absoluteLocation', () => {
19
25
  expect(absoluteLocation('/a', '/a/b')).to.equal('/a/b');
@@ -101,6 +107,7 @@ describe('utils 测试', () => {
101
107
  `;--x:1px;font-size:14px;content:'*';`,
102
108
  );
103
109
  expect(classMap({ foo: true, content: false })).to.equal(` foo `);
104
- expect(exportPartsMap({ foo: 'bar', content: 'content' })).to.equal(`,foo:bar,content:content,`);
110
+ expect(exportPartsMap({ foo: 'bar', content: 'content', false: false })).to.equal(`,foo:bar,content,`);
111
+ expect(exportPartsMap({ foo: 'bar', content: true })).to.equal(`,foo:bar,content,`);
105
112
  });
106
113
  });