@jvs-milkdown/ctx 1.0.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.
Files changed (50) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +11 -0
  3. package/lib/context/container.d.ts +9 -0
  4. package/lib/context/container.d.ts.map +1 -0
  5. package/lib/context/index.d.ts +3 -0
  6. package/lib/context/index.d.ts.map +1 -0
  7. package/lib/context/slice.d.ts +23 -0
  8. package/lib/context/slice.d.ts.map +1 -0
  9. package/lib/index.d.ts +5 -0
  10. package/lib/index.d.ts.map +1 -0
  11. package/lib/index.js +300 -0
  12. package/lib/index.js.map +1 -0
  13. package/lib/inspector/index.d.ts +3 -0
  14. package/lib/inspector/index.d.ts.map +1 -0
  15. package/lib/inspector/inspector.d.ts +37 -0
  16. package/lib/inspector/inspector.d.ts.map +1 -0
  17. package/lib/inspector/meta.d.ts +8 -0
  18. package/lib/inspector/meta.d.ts.map +1 -0
  19. package/lib/plugin/ctx.d.ts +26 -0
  20. package/lib/plugin/ctx.d.ts.map +1 -0
  21. package/lib/plugin/index.d.ts +3 -0
  22. package/lib/plugin/index.d.ts.map +1 -0
  23. package/lib/plugin/types.d.ts +9 -0
  24. package/lib/plugin/types.d.ts.map +1 -0
  25. package/lib/timer/clock.d.ts +9 -0
  26. package/lib/timer/clock.d.ts.map +1 -0
  27. package/lib/timer/index.d.ts +3 -0
  28. package/lib/timer/index.d.ts.map +1 -0
  29. package/lib/timer/timer.d.ts +19 -0
  30. package/lib/timer/timer.d.ts.map +1 -0
  31. package/lib/tsconfig.tsbuildinfo +1 -0
  32. package/package.json +39 -0
  33. package/src/context/container.spec.ts +54 -0
  34. package/src/context/container.ts +48 -0
  35. package/src/context/index.ts +2 -0
  36. package/src/context/slice.spec.ts +116 -0
  37. package/src/context/slice.ts +108 -0
  38. package/src/index.ts +4 -0
  39. package/src/inspector/index.ts +2 -0
  40. package/src/inspector/inspector.ts +124 -0
  41. package/src/inspector/meta.ts +17 -0
  42. package/src/plugin/ctx.spec.ts +110 -0
  43. package/src/plugin/ctx.ts +136 -0
  44. package/src/plugin/index.ts +2 -0
  45. package/src/plugin/types.ts +43 -0
  46. package/src/timer/clock.spec.ts +27 -0
  47. package/src/timer/clock.ts +29 -0
  48. package/src/timer/index.ts +2 -0
  49. package/src/timer/timer.spec.ts +29 -0
  50. package/src/timer/timer.ts +109 -0
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2020-present Mirone
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,11 @@
1
+ # @jvs-milkdown/ctx
2
+
3
+ The core module of [milkdown](https://milkdown.dev/).
4
+
5
+ # Official Documentation
6
+
7
+ Documentation can be found on the [Milkdown website](https://milkdown.dev/).
8
+
9
+ # License
10
+
11
+ Milkdown is open sourced software licensed under [MIT license](https://github.com/Milkdown/milkdown/blob/main/LICENSE).
@@ -0,0 +1,9 @@
1
+ import type { Slice, SliceType } from './slice';
2
+ export type SliceMap = Map<symbol, Slice>;
3
+ export declare class Container {
4
+ sliceMap: SliceMap;
5
+ get: <T, N extends string = string>(slice: SliceType<T, N> | N) => Slice<T, N>;
6
+ remove: <T, N extends string = string>(slice: SliceType<T, N> | N) => void;
7
+ has: <T, N extends string = string>(slice: SliceType<T, N> | N) => boolean;
8
+ }
9
+ //# sourceMappingURL=container.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"container.d.ts","sourceRoot":"","sources":["../../src/context/container.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,KAAK,EAAE,SAAS,EAAE,MAAM,SAAS,CAAA;AAG/C,MAAM,MAAM,QAAQ,GAAG,GAAG,CAAC,MAAM,EAAE,KAAK,CAAC,CAAA;AAGzC,qBAAa,SAAS;IAEpB,QAAQ,EAAE,QAAQ,CAAY;IAG9B,GAAG,GAAI,CAAC,EAAE,CAAC,SAAS,MAAM,GAAG,MAAM,EACjC,OAAO,SAAS,CAAC,CAAC,EAAE,CAAC,CAAC,GAAG,CAAC,KACzB,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAWb;IAGD,MAAM,GAAI,CAAC,EAAE,CAAC,SAAS,MAAM,GAAG,MAAM,EAAE,OAAO,SAAS,CAAC,CAAC,EAAE,CAAC,CAAC,GAAG,CAAC,KAAG,IAAI,CASxE;IAGD,GAAG,GAAI,CAAC,EAAE,CAAC,SAAS,MAAM,GAAG,MAAM,EAAE,OAAO,SAAS,CAAC,CAAC,EAAE,CAAC,CAAC,GAAG,CAAC,KAAG,OAAO,CAKxE;CACF"}
@@ -0,0 +1,3 @@
1
+ export * from './container';
2
+ export * from './slice';
3
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/context/index.ts"],"names":[],"mappings":"AAAA,cAAc,aAAa,CAAA;AAC3B,cAAc,SAAS,CAAA"}
@@ -0,0 +1,23 @@
1
+ import type { SliceMap } from './container';
2
+ export declare class Slice<T = any, N extends string = string> {
3
+ #private;
4
+ readonly type: SliceType<T, N>;
5
+ constructor(container: SliceMap, value: T, type: SliceType<T, N>);
6
+ on(watcher: (value: T) => unknown): () => void;
7
+ once(watcher: (value: T) => unknown): () => void;
8
+ off(watcher: (value: T) => unknown): void;
9
+ offAll(): void;
10
+ set: (value: T) => void;
11
+ get: () => T;
12
+ update: (updater: (prev: T) => T) => void;
13
+ }
14
+ export declare class SliceType<T = any, N extends string = string> {
15
+ readonly id: symbol;
16
+ readonly name: N;
17
+ readonly _typeInfo: () => T;
18
+ readonly _defaultValue: T;
19
+ constructor(value: T, name: N);
20
+ create(container: SliceMap, value?: T): Slice<T, N>;
21
+ }
22
+ export declare const createSlice: <T = any, N extends string = string>(value: T, name: N) => SliceType<T, N>;
23
+ //# sourceMappingURL=slice.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"slice.d.ts","sourceRoot":"","sources":["../../src/context/slice.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAA;AAG3C,qBAAa,KAAK,CAAC,CAAC,GAAG,GAAG,EAAE,CAAC,SAAS,MAAM,GAAG,MAAM;;IAEnD,QAAQ,CAAC,IAAI,EAAE,SAAS,CAAC,CAAC,EAAE,CAAC,CAAC,CAAA;gBAclB,SAAS,EAAE,QAAQ,EAAE,KAAK,EAAE,CAAC,EAAE,IAAI,EAAE,SAAS,CAAC,CAAC,EAAE,CAAC,CAAC;IAQhE,EAAE,CAAC,OAAO,EAAE,CAAC,KAAK,EAAE,CAAC,KAAK,OAAO;IAUjC,IAAI,CAAC,OAAO,EAAE,CAAC,KAAK,EAAE,CAAC,KAAK,OAAO;IASnC,GAAG,CAAC,OAAO,EAAE,CAAC,KAAK,EAAE,CAAC,KAAK,OAAO;IAKlC,MAAM;IAKN,GAAG,GAAI,OAAO,CAAC,UAGd;IAGD,GAAG,UAAoB;IAGvB,MAAM,GAAI,SAAS,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC,UAGhC;CACF;AAGD,qBAAa,SAAS,CAAC,CAAC,GAAG,GAAG,EAAE,CAAC,SAAS,MAAM,GAAG,MAAM;IAEvD,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAA;IAEnB,QAAQ,CAAC,IAAI,EAAE,CAAC,CAAA;IAEhB,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC,CAAA;IAE3B,QAAQ,CAAC,aAAa,EAAE,CAAC,CAAA;gBAIb,KAAK,EAAE,CAAC,EAAE,IAAI,EAAE,CAAC;IAW7B,MAAM,CAAC,SAAS,EAAE,QAAQ,EAAE,KAAK,GAAE,CAAsB,GAAG,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC;CAGxE;AAID,eAAO,MAAM,WAAW,GAAI,CAAC,GAAG,GAAG,EAAE,CAAC,SAAS,MAAM,GAAG,MAAM,EAC5D,OAAO,CAAC,EACR,MAAM,CAAC,oBACsB,CAAA"}
package/lib/index.d.ts ADDED
@@ -0,0 +1,5 @@
1
+ export * from './context';
2
+ export * from './plugin';
3
+ export * from './timer';
4
+ export * from './inspector';
5
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,WAAW,CAAA;AACzB,cAAc,UAAU,CAAA;AACxB,cAAc,SAAS,CAAA;AACvB,cAAc,aAAa,CAAA"}
package/lib/index.js ADDED
@@ -0,0 +1,300 @@
1
+ import { contextNotFound, ctxCallOutOfScope, timerNotFound } from "@jvs-milkdown/exception";
2
+ //#region src/context/container.ts
3
+ var Container = class {
4
+ constructor() {
5
+ this.sliceMap = /* @__PURE__ */ new Map();
6
+ this.get = (slice) => {
7
+ const context = typeof slice === "string" ? [...this.sliceMap.values()].find((x) => x.type.name === slice) : this.sliceMap.get(slice.id);
8
+ if (!context) throw contextNotFound(typeof slice === "string" ? slice : slice.name);
9
+ return context;
10
+ };
11
+ this.remove = (slice) => {
12
+ const context = typeof slice === "string" ? [...this.sliceMap.values()].find((x) => x.type.name === slice) : this.sliceMap.get(slice.id);
13
+ if (!context) return;
14
+ this.sliceMap.delete(context.type.id);
15
+ };
16
+ this.has = (slice) => {
17
+ if (typeof slice === "string") return [...this.sliceMap.values()].some((x) => x.type.name === slice);
18
+ return this.sliceMap.has(slice.id);
19
+ };
20
+ }
21
+ };
22
+ //#endregion
23
+ //#region src/context/slice.ts
24
+ var Slice = class {
25
+ #watchers = [];
26
+ #value;
27
+ #emit = () => {
28
+ this.#watchers.forEach((watcher) => watcher(this.#value));
29
+ };
30
+ constructor(container, value, type) {
31
+ this.set = (value) => {
32
+ this.#value = value;
33
+ this.#emit();
34
+ };
35
+ this.get = () => this.#value;
36
+ this.update = (updater) => {
37
+ this.#value = updater(this.#value);
38
+ this.#emit();
39
+ };
40
+ this.type = type;
41
+ this.#value = value;
42
+ container.set(type.id, this);
43
+ }
44
+ on(watcher) {
45
+ this.#watchers.push(watcher);
46
+ return () => {
47
+ this.#watchers = this.#watchers.filter((w) => w !== watcher);
48
+ };
49
+ }
50
+ once(watcher) {
51
+ const off = this.on((value) => {
52
+ watcher(value);
53
+ off();
54
+ });
55
+ return off;
56
+ }
57
+ off(watcher) {
58
+ this.#watchers = this.#watchers.filter((w) => w !== watcher);
59
+ }
60
+ offAll() {
61
+ this.#watchers = [];
62
+ }
63
+ };
64
+ var SliceType = class {
65
+ constructor(value, name) {
66
+ this.id = Symbol(`Context-${name}`);
67
+ this.name = name;
68
+ this._defaultValue = value;
69
+ this._typeInfo = () => {
70
+ throw ctxCallOutOfScope();
71
+ };
72
+ }
73
+ create(container, value = this._defaultValue) {
74
+ return new Slice(container, value, this);
75
+ }
76
+ };
77
+ var createSlice = (value, name) => new SliceType(value, name);
78
+ //#endregion
79
+ //#region src/inspector/inspector.ts
80
+ var Inspector = class {
81
+ #meta;
82
+ #container;
83
+ #clock;
84
+ #injectedSlices = /* @__PURE__ */ new Set();
85
+ #consumedSlices = /* @__PURE__ */ new Set();
86
+ #recordedTimers = /* @__PURE__ */ new Map();
87
+ #waitTimers = /* @__PURE__ */ new Map();
88
+ constructor(container, clock, meta) {
89
+ this.read = () => {
90
+ return {
91
+ metadata: this.#meta,
92
+ injectedSlices: [...this.#injectedSlices].map((slice) => ({
93
+ name: typeof slice === "string" ? slice : slice.name,
94
+ value: this.#getSlice(slice)
95
+ })),
96
+ consumedSlices: [...this.#consumedSlices].map((slice) => ({
97
+ name: typeof slice === "string" ? slice : slice.name,
98
+ value: this.#getSlice(slice)
99
+ })),
100
+ recordedTimers: [...this.#recordedTimers].map(([timer, { duration }]) => ({
101
+ name: timer.name,
102
+ duration,
103
+ status: this.#getTimer(timer)
104
+ })),
105
+ waitTimers: [...this.#waitTimers].map(([timer, { duration }]) => ({
106
+ name: timer.name,
107
+ duration,
108
+ status: this.#getTimer(timer)
109
+ }))
110
+ };
111
+ };
112
+ this.onRecord = (timerType) => {
113
+ this.#recordedTimers.set(timerType, {
114
+ start: Date.now(),
115
+ duration: 0
116
+ });
117
+ };
118
+ this.onClear = (timerType) => {
119
+ this.#recordedTimers.delete(timerType);
120
+ };
121
+ this.onDone = (timerType) => {
122
+ const timer = this.#recordedTimers.get(timerType);
123
+ if (!timer) return;
124
+ timer.duration = Date.now() - timer.start;
125
+ };
126
+ this.onWait = (timerType, promise) => {
127
+ const start = Date.now();
128
+ promise.finally(() => {
129
+ this.#waitTimers.set(timerType, { duration: Date.now() - start });
130
+ }).catch(console.error);
131
+ };
132
+ this.onInject = (sliceType) => {
133
+ this.#injectedSlices.add(sliceType);
134
+ };
135
+ this.onRemove = (sliceType) => {
136
+ this.#injectedSlices.delete(sliceType);
137
+ };
138
+ this.onUse = (sliceType) => {
139
+ this.#consumedSlices.add(sliceType);
140
+ };
141
+ this.#container = container;
142
+ this.#clock = clock;
143
+ this.#meta = meta;
144
+ }
145
+ #getSlice = (sliceType) => {
146
+ return this.#container.get(sliceType).get();
147
+ };
148
+ #getTimer = (timerType) => {
149
+ return this.#clock.get(timerType).status;
150
+ };
151
+ };
152
+ //#endregion
153
+ //#region src/plugin/ctx.ts
154
+ var Ctx = class Ctx {
155
+ #container;
156
+ #clock;
157
+ #meta;
158
+ #inspector;
159
+ constructor(container, clock, meta) {
160
+ this.produce = (meta) => {
161
+ if (meta && Object.keys(meta).length) return new Ctx(this.#container, this.#clock, { ...meta });
162
+ return this;
163
+ };
164
+ this.inject = (sliceType, value) => {
165
+ const slice = sliceType.create(this.#container.sliceMap);
166
+ if (value != null) slice.set(value);
167
+ this.#inspector?.onInject(sliceType);
168
+ return this;
169
+ };
170
+ this.remove = (sliceType) => {
171
+ this.#container.remove(sliceType);
172
+ this.#inspector?.onRemove(sliceType);
173
+ return this;
174
+ };
175
+ this.record = (timerType) => {
176
+ timerType.create(this.#clock.store);
177
+ this.#inspector?.onRecord(timerType);
178
+ return this;
179
+ };
180
+ this.clearTimer = (timerType) => {
181
+ this.#clock.remove(timerType);
182
+ this.#inspector?.onClear(timerType);
183
+ return this;
184
+ };
185
+ this.isInjected = (sliceType) => this.#container.has(sliceType);
186
+ this.isRecorded = (timerType) => this.#clock.has(timerType);
187
+ this.use = (sliceType) => {
188
+ this.#inspector?.onUse(sliceType);
189
+ return this.#container.get(sliceType);
190
+ };
191
+ this.get = (sliceType) => this.use(sliceType).get();
192
+ this.set = (sliceType, value) => this.use(sliceType).set(value);
193
+ this.update = (sliceType, updater) => this.use(sliceType).update(updater);
194
+ this.timer = (timer) => this.#clock.get(timer);
195
+ this.done = (timer) => {
196
+ this.timer(timer).done();
197
+ this.#inspector?.onDone(timer);
198
+ };
199
+ this.wait = (timer) => {
200
+ const promise = this.timer(timer).start();
201
+ this.#inspector?.onWait(timer, promise);
202
+ return promise;
203
+ };
204
+ this.waitTimers = async (slice) => {
205
+ await Promise.all(this.get(slice).map((x) => this.wait(x)));
206
+ };
207
+ this.#container = container;
208
+ this.#clock = clock;
209
+ this.#meta = meta;
210
+ if (meta) this.#inspector = new Inspector(container, clock, meta);
211
+ }
212
+ get meta() {
213
+ return this.#meta;
214
+ }
215
+ get inspector() {
216
+ return this.#inspector;
217
+ }
218
+ };
219
+ //#endregion
220
+ //#region src/timer/clock.ts
221
+ var Clock = class {
222
+ constructor() {
223
+ this.store = /* @__PURE__ */ new Map();
224
+ this.get = (timer) => {
225
+ const meta = this.store.get(timer.id);
226
+ if (!meta) throw timerNotFound(timer.name);
227
+ return meta;
228
+ };
229
+ this.remove = (timer) => {
230
+ this.store.delete(timer.id);
231
+ };
232
+ this.has = (timer) => {
233
+ return this.store.has(timer.id);
234
+ };
235
+ }
236
+ };
237
+ //#endregion
238
+ //#region src/timer/timer.ts
239
+ var Timer = class {
240
+ #promise = null;
241
+ #listener = null;
242
+ #eventUniqId;
243
+ #status = "pending";
244
+ constructor(clock, type) {
245
+ this.start = () => {
246
+ this.#promise ??= new Promise((resolve, reject) => {
247
+ this.#listener = (e) => {
248
+ if (!(e instanceof CustomEvent)) return;
249
+ if (e.detail.id === this.#eventUniqId) {
250
+ this.#status = "resolved";
251
+ this.#removeListener();
252
+ e.stopImmediatePropagation();
253
+ resolve();
254
+ }
255
+ };
256
+ this.#waitTimeout(() => {
257
+ if (this.#status === "pending") this.#status = "rejected";
258
+ this.#removeListener();
259
+ reject(/* @__PURE__ */ new Error(`Timing ${this.type.name} timeout.`));
260
+ });
261
+ this.#status = "pending";
262
+ addEventListener(this.type.name, this.#listener);
263
+ });
264
+ return this.#promise;
265
+ };
266
+ this.done = () => {
267
+ const event = new CustomEvent(this.type.name, { detail: { id: this.#eventUniqId } });
268
+ dispatchEvent(event);
269
+ };
270
+ this.#eventUniqId = Symbol(type.name);
271
+ this.type = type;
272
+ clock.set(type.id, this);
273
+ }
274
+ get status() {
275
+ return this.#status;
276
+ }
277
+ #removeListener = () => {
278
+ if (this.#listener) removeEventListener(this.type.name, this.#listener);
279
+ };
280
+ #waitTimeout = (ifTimeout) => {
281
+ setTimeout(() => {
282
+ ifTimeout();
283
+ }, this.type.timeout);
284
+ };
285
+ };
286
+ var TimerType = class {
287
+ constructor(name, timeout = 3e3) {
288
+ this.create = (clock) => {
289
+ return new Timer(clock, this);
290
+ };
291
+ this.id = Symbol(`Timer-${name}`);
292
+ this.name = name;
293
+ this.timeout = timeout;
294
+ }
295
+ };
296
+ var createTimer = (name, timeout = 3e3) => new TimerType(name, timeout);
297
+ //#endregion
298
+ export { Clock, Container, Ctx, Inspector, Slice, SliceType, Timer, TimerType, createSlice, createTimer };
299
+
300
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","names":["#watchers","#value","#emit","#meta","#container","#clock","#injectedSlices","#consumedSlices","#recordedTimers","#waitTimers","#getSlice","#getTimer","#container","#clock","#meta","#inspector","#eventUniqId","#promise","#listener","#status","#removeListener","#waitTimeout"],"sources":["../src/context/container.ts","../src/context/slice.ts","../src/inspector/inspector.ts","../src/plugin/ctx.ts","../src/timer/clock.ts","../src/timer/timer.ts"],"sourcesContent":["import { contextNotFound } from '@jvs-milkdown/exception'\n\nimport type { Slice, SliceType } from './slice'\n\n/// @internal\nexport type SliceMap = Map<symbol, Slice>\n\n/// Container is a map of slices.\nexport class Container {\n /// @internal\n sliceMap: SliceMap = new Map()\n\n /// Get a slice from the container by slice type or slice name.\n get = <T, N extends string = string>(\n slice: SliceType<T, N> | N\n ): Slice<T, N> => {\n const context =\n typeof slice === 'string'\n ? [...this.sliceMap.values()].find((x) => x.type.name === slice)\n : this.sliceMap.get(slice.id)\n\n if (!context) {\n const name = typeof slice === 'string' ? slice : slice.name\n throw contextNotFound(name)\n }\n return context as Slice<T, N>\n }\n\n /// Remove a slice from the container by slice type or slice name.\n remove = <T, N extends string = string>(slice: SliceType<T, N> | N): void => {\n const context =\n typeof slice === 'string'\n ? [...this.sliceMap.values()].find((x) => x.type.name === slice)\n : this.sliceMap.get(slice.id)\n\n if (!context) return\n\n this.sliceMap.delete(context.type.id)\n }\n\n /// Check if the container has a slice by slice type or slice name.\n has = <T, N extends string = string>(slice: SliceType<T, N> | N): boolean => {\n if (typeof slice === 'string')\n return [...this.sliceMap.values()].some((x) => x.type.name === slice)\n\n return this.sliceMap.has(slice.id)\n }\n}\n","import { ctxCallOutOfScope } from '@jvs-milkdown/exception'\n\nimport type { SliceMap } from './container'\n\n/// Slice is a value of slice type.\nexport class Slice<T = any, N extends string = string> {\n /// The type of the slice.\n readonly type: SliceType<T, N>\n\n /// @internal\n #watchers: Array<(value: T) => unknown> = []\n\n /// @internal\n #value: T\n\n /// @internal\n #emit = () => {\n this.#watchers.forEach((watcher) => watcher(this.#value))\n }\n\n /// @internal\n constructor(container: SliceMap, value: T, type: SliceType<T, N>) {\n this.type = type\n this.#value = value\n container.set(type.id, this)\n }\n\n /// Add a watcher for changes in the slice.\n /// Returns a function to remove the watcher.\n on(watcher: (value: T) => unknown) {\n this.#watchers.push(watcher)\n return () => {\n this.#watchers = this.#watchers.filter((w) => w !== watcher)\n }\n }\n\n /// Add a one-time watcher for changes in the slice.\n /// The watcher will be removed after it is called.\n /// Returns a function to remove the watcher.\n once(watcher: (value: T) => unknown) {\n const off = this.on((value) => {\n watcher(value)\n off()\n })\n return off\n }\n\n /// Remove a watcher.\n off(watcher: (value: T) => unknown) {\n this.#watchers = this.#watchers.filter((w) => w !== watcher)\n }\n\n /// Remove all watchers.\n offAll() {\n this.#watchers = []\n }\n\n /// Set the value of the slice.\n set = (value: T) => {\n this.#value = value\n this.#emit()\n }\n\n /// Get the value of the slice.\n get = () => this.#value\n\n /// Update the value of the slice with a callback.\n update = (updater: (prev: T) => T) => {\n this.#value = updater(this.#value)\n this.#emit()\n }\n}\n\n/// Slice type can be used to create slices in different containers.\nexport class SliceType<T = any, N extends string = string> {\n /// The unique id of the slice type.\n readonly id: symbol\n /// The name of the slice type.\n readonly name: N\n /// @internal\n readonly _typeInfo: () => T\n /// @internal\n readonly _defaultValue: T\n\n /// Create a slice type with a default value and a name.\n /// The name should be unique in the container.\n constructor(value: T, name: N) {\n this.id = Symbol(`Context-${name}`)\n this.name = name\n this._defaultValue = value\n this._typeInfo = (): T => {\n throw ctxCallOutOfScope()\n }\n }\n\n /// Create a slice with a container.\n /// You can also pass a value to override the default value.\n create(container: SliceMap, value: T = this._defaultValue): Slice<T, N> {\n return new Slice(container, value, this)\n }\n}\n\n/// Create a slice type with a default value and a name.\n/// This is equivalent to `new SliceType(value, name)`.\nexport const createSlice = <T = any, N extends string = string>(\n value: T,\n name: N\n) => new SliceType(value, name)\n","import type { Container, SliceType } from '../context'\nimport type { Clock, TimerStatus, TimerType } from '../timer'\nimport type { Meta } from './meta'\n\nexport interface Telemetry {\n metadata: Meta\n injectedSlices: { name: string; value: unknown }[]\n consumedSlices: { name: string; value: unknown }[]\n recordedTimers: { name: string; duration: number; status: TimerStatus }[]\n waitTimers: { name: string; duration: number; status: TimerStatus }[]\n}\n\n/// The inspector object that is used to inspect the runtime environment of a ctx.\nexport class Inspector {\n /// @internal\n readonly #meta: Meta\n\n /// @internal\n readonly #container: Container\n\n /// @internal\n readonly #clock: Clock\n\n /// @internal\n readonly #injectedSlices: Set<SliceType | string> = new Set()\n\n /// @internal\n readonly #consumedSlices: Set<SliceType | string> = new Set()\n\n /// @internal\n readonly #recordedTimers: Map<\n TimerType,\n { duration: number; start: number }\n > = new Map()\n\n /// @internal\n readonly #waitTimers: Map<TimerType, { duration: number }> = new Map()\n\n /// Create an inspector with container, clock and metadata.\n constructor(container: Container, clock: Clock, meta: Meta) {\n this.#container = container\n this.#clock = clock\n this.#meta = meta\n }\n\n /// Read the runtime telemetry as an object of the ctx.\n read = (): Telemetry => {\n return {\n metadata: this.#meta,\n injectedSlices: [...this.#injectedSlices].map((slice) => ({\n name: typeof slice === 'string' ? slice : slice.name,\n value: this.#getSlice(slice),\n })),\n consumedSlices: [...this.#consumedSlices].map((slice) => ({\n name: typeof slice === 'string' ? slice : slice.name,\n value: this.#getSlice(slice),\n })),\n recordedTimers: [...this.#recordedTimers].map(\n ([timer, { duration }]) => ({\n name: timer.name,\n duration,\n status: this.#getTimer(timer),\n })\n ),\n waitTimers: [...this.#waitTimers].map(([timer, { duration }]) => ({\n name: timer.name,\n duration,\n status: this.#getTimer(timer),\n })),\n }\n }\n\n /// @internal\n readonly onRecord = (timerType: TimerType) => {\n this.#recordedTimers.set(timerType, { start: Date.now(), duration: 0 })\n }\n\n /// @internal\n readonly onClear = (timerType: TimerType) => {\n this.#recordedTimers.delete(timerType)\n }\n\n /// @internal\n readonly onDone = (timerType: TimerType) => {\n const timer = this.#recordedTimers.get(timerType)\n if (!timer) return\n timer.duration = Date.now() - timer.start\n }\n\n /// @internal\n readonly onWait = (timerType: TimerType, promise: Promise<void>) => {\n const start = Date.now()\n promise\n .finally(() => {\n this.#waitTimers.set(timerType, { duration: Date.now() - start })\n })\n .catch(console.error)\n }\n\n /// @internal\n readonly onInject = (sliceType: SliceType | string) => {\n this.#injectedSlices.add(sliceType)\n }\n\n /// @internal\n readonly onRemove = (sliceType: SliceType | string) => {\n this.#injectedSlices.delete(sliceType)\n }\n\n /// @internal\n readonly onUse = (sliceType: SliceType | string) => {\n this.#consumedSlices.add(sliceType)\n }\n\n /// @internal\n #getSlice = (sliceType: SliceType | string) => {\n return this.#container.get(sliceType).get()\n }\n\n /// @internal\n #getTimer = (timerType: TimerType) => {\n return this.#clock.get(timerType).status\n }\n}\n","import type { Container, Slice, SliceType } from '../context'\nimport type { Meta } from '../inspector'\nimport type { Clock, TimerType } from '../timer'\n\nimport { Inspector } from '../inspector'\n\n/// The ctx object that can be accessed in plugin and action.\nexport class Ctx {\n /// @internal\n readonly #container: Container\n /// @internal\n readonly #clock: Clock\n /// @internal\n readonly #meta?: Meta\n /// @internal\n readonly #inspector?: Inspector\n\n /// Create a ctx object with container and clock.\n constructor(container: Container, clock: Clock, meta?: Meta) {\n this.#container = container\n this.#clock = clock\n this.#meta = meta\n if (meta) this.#inspector = new Inspector(container, clock, meta)\n }\n\n /// Get metadata of the ctx.\n get meta() {\n return this.#meta\n }\n\n /// Get the inspector of the ctx.\n get inspector() {\n return this.#inspector\n }\n\n /// Produce a new ctx with metadata.\n /// The new ctx will link to the same container and clock with the current ctx.\n /// If the metadata is empty, it will return the current ctx.\n readonly produce = (meta?: Meta) => {\n if (meta && Object.keys(meta).length)\n return new Ctx(this.#container, this.#clock, { ...meta })\n\n return this\n }\n\n /// Add a slice into the ctx.\n readonly inject = <T>(sliceType: SliceType<T>, value?: T) => {\n const slice = sliceType.create(this.#container.sliceMap)\n if (value != null) slice.set(value)\n\n this.#inspector?.onInject(sliceType)\n\n return this\n }\n\n /// Remove a slice from the ctx.\n readonly remove = <T, N extends string = string>(\n sliceType: SliceType<T, N> | N\n ) => {\n this.#container.remove(sliceType)\n this.#inspector?.onRemove(sliceType)\n return this\n }\n\n /// Add a timer into the ctx.\n readonly record = (timerType: TimerType) => {\n timerType.create(this.#clock.store)\n this.#inspector?.onRecord(timerType)\n return this\n }\n\n /// Remove a timer from the ctx.\n readonly clearTimer = (timerType: TimerType) => {\n this.#clock.remove(timerType)\n this.#inspector?.onClear(timerType)\n return this\n }\n\n /// Check if the ctx has a slice.\n readonly isInjected = <T, N extends string = string>(\n sliceType: SliceType<T, N> | N\n ) => this.#container.has(sliceType)\n\n /// Check if the ctx has a timer.\n readonly isRecorded = (timerType: TimerType) => this.#clock.has(timerType)\n\n /// Get a slice from the ctx.\n readonly use = <T, N extends string = string>(\n sliceType: SliceType<T, N> | N\n ): Slice<T, N> => {\n this.#inspector?.onUse(sliceType)\n return this.#container.get(sliceType)\n }\n\n /// Get a slice value from the ctx.\n readonly get = <T, N extends string>(sliceType: SliceType<T, N> | N) =>\n this.use(sliceType).get()\n\n /// Get a slice value from the ctx.\n readonly set = <T, N extends string>(\n sliceType: SliceType<T, N> | N,\n value: T\n ) => this.use(sliceType).set(value)\n\n /// Update a slice value from the ctx by a callback.\n readonly update = <T, N extends string>(\n sliceType: SliceType<T, N> | N,\n updater: (prev: T) => T\n ) => this.use(sliceType).update(updater)\n\n /// Get a timer from the ctx.\n readonly timer = (timer: TimerType) => this.#clock.get(timer)\n\n /// Resolve a timer from the ctx.\n readonly done = (timer: TimerType) => {\n this.timer(timer).done()\n this.#inspector?.onDone(timer)\n }\n\n /// Start a timer from the ctx.\n readonly wait = (timer: TimerType) => {\n const promise = this.timer(timer).start()\n this.#inspector?.onWait(timer, promise)\n return promise\n }\n\n /// Start a list of timers from the ctx, the list is stored in a slice in the ctx.\n /// This is equivalent to\n ///\n /// ```typescript\n /// Promise.all(ctx.get(slice).map(x => ctx.wait(x))).\n /// ```\n readonly waitTimers = async (slice: SliceType<TimerType[]>) => {\n await Promise.all(this.get(slice).map((x) => this.wait(x)))\n }\n}\n","import { timerNotFound } from '@jvs-milkdown/exception'\n\nimport type { Timer, TimerType } from './timer'\n\n/// @internal\nexport type TimerMap = Map<symbol, Timer>\n\n/// Container is a map of timers.\nexport class Clock {\n /// @internal\n readonly store: TimerMap = new Map()\n\n /// Get a timer from the clock by timer type.\n get = (timer: TimerType) => {\n const meta = this.store.get(timer.id)\n if (!meta) throw timerNotFound(timer.name)\n return meta\n }\n\n /// Remove a timer from the clock by timer type.\n remove = (timer: TimerType) => {\n this.store.delete(timer.id)\n }\n\n // Check if the clock has a timer by timer type.\n has = (timer: TimerType) => {\n return this.store.has(timer.id)\n }\n}\n","import type { TimerMap } from './clock'\n\nexport type TimerStatus = 'pending' | 'resolved' | 'rejected'\n\n/// Timer is a promise that can be resolved by calling done.\nexport class Timer {\n /// The type of the timer.\n readonly type: TimerType\n\n /// @internal\n #promise: Promise<void> | null = null\n /// @internal\n #listener: EventListener | null = null\n /// @internal\n readonly #eventUniqId: symbol\n /// @internal\n #status: TimerStatus = 'pending'\n\n /// @internal\n constructor(clock: TimerMap, type: TimerType) {\n this.#eventUniqId = Symbol(type.name)\n this.type = type\n clock.set(type.id, this)\n }\n\n /// The status of the timer.\n /// Can be `pending`, `resolved` or `rejected`.\n get status() {\n return this.#status\n }\n\n /// Start the timer, which will return a promise.\n /// If the timer is already started, it will return the same promise.\n /// If the timer is not resolved in the timeout, it will reject the promise.\n start = () => {\n this.#promise ??= new Promise((resolve, reject) => {\n this.#listener = (e: Event) => {\n if (!(e instanceof CustomEvent)) return\n\n if (e.detail.id === this.#eventUniqId) {\n this.#status = 'resolved'\n this.#removeListener()\n e.stopImmediatePropagation()\n resolve()\n }\n }\n\n this.#waitTimeout(() => {\n if (this.#status === 'pending') this.#status = 'rejected'\n\n this.#removeListener()\n reject(new Error(`Timing ${this.type.name} timeout.`))\n })\n\n this.#status = 'pending'\n addEventListener(this.type.name, this.#listener)\n })\n\n return this.#promise\n }\n\n /// Resolve the timer.\n done = () => {\n const event = new CustomEvent(this.type.name, {\n detail: { id: this.#eventUniqId },\n })\n dispatchEvent(event)\n }\n\n /// @internal\n #removeListener = () => {\n if (this.#listener) removeEventListener(this.type.name, this.#listener)\n }\n\n /// @internal\n #waitTimeout = (ifTimeout: () => void) => {\n setTimeout(() => {\n ifTimeout()\n }, this.type.timeout)\n }\n}\n\n/// Timer type can be used to create timers in different clocks.\nexport class TimerType {\n /// The unique id of the timer type.\n readonly id: symbol\n /// The name of the timer type.\n readonly name: string\n /// The timeout of the timer type.\n readonly timeout: number\n\n /// Create a timer type with a name and a timeout.\n /// The name should be unique in the clock.\n constructor(name: string, timeout = 3000) {\n this.id = Symbol(`Timer-${name}`)\n this.name = name\n this.timeout = timeout\n }\n\n /// Create a timer with a clock.\n create = (clock: TimerMap): Timer => {\n return new Timer(clock, this)\n }\n}\n\n/// Create a timer type with a name and a timeout.\n/// This is equivalent to `new TimerType(name, timeout)`.\nexport const createTimer = (name: string, timeout = 3000) =>\n new TimerType(name, timeout)\n"],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ export * from './meta';
2
+ export * from './inspector';
3
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/inspector/index.ts"],"names":[],"mappings":"AAAA,cAAc,QAAQ,CAAA;AACtB,cAAc,aAAa,CAAA"}
@@ -0,0 +1,37 @@
1
+ import type { Container, SliceType } from '../context';
2
+ import type { Clock, TimerStatus, TimerType } from '../timer';
3
+ import type { Meta } from './meta';
4
+ export interface Telemetry {
5
+ metadata: Meta;
6
+ injectedSlices: {
7
+ name: string;
8
+ value: unknown;
9
+ }[];
10
+ consumedSlices: {
11
+ name: string;
12
+ value: unknown;
13
+ }[];
14
+ recordedTimers: {
15
+ name: string;
16
+ duration: number;
17
+ status: TimerStatus;
18
+ }[];
19
+ waitTimers: {
20
+ name: string;
21
+ duration: number;
22
+ status: TimerStatus;
23
+ }[];
24
+ }
25
+ export declare class Inspector {
26
+ #private;
27
+ constructor(container: Container, clock: Clock, meta: Meta);
28
+ read: () => Telemetry;
29
+ readonly onRecord: (timerType: TimerType) => void;
30
+ readonly onClear: (timerType: TimerType) => void;
31
+ readonly onDone: (timerType: TimerType) => void;
32
+ readonly onWait: (timerType: TimerType, promise: Promise<void>) => void;
33
+ readonly onInject: (sliceType: SliceType | string) => void;
34
+ readonly onRemove: (sliceType: SliceType | string) => void;
35
+ readonly onUse: (sliceType: SliceType | string) => void;
36
+ }
37
+ //# sourceMappingURL=inspector.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"inspector.d.ts","sourceRoot":"","sources":["../../src/inspector/inspector.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,SAAS,EAAE,MAAM,YAAY,CAAA;AACtD,OAAO,KAAK,EAAE,KAAK,EAAE,WAAW,EAAE,SAAS,EAAE,MAAM,UAAU,CAAA;AAC7D,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,QAAQ,CAAA;AAElC,MAAM,WAAW,SAAS;IACxB,QAAQ,EAAE,IAAI,CAAA;IACd,cAAc,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,OAAO,CAAA;KAAE,EAAE,CAAA;IAClD,cAAc,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,OAAO,CAAA;KAAE,EAAE,CAAA;IAClD,cAAc,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,WAAW,CAAA;KAAE,EAAE,CAAA;IACzE,UAAU,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,WAAW,CAAA;KAAE,EAAE,CAAA;CACtE;AAGD,qBAAa,SAAS;;gBA0BR,SAAS,EAAE,SAAS,EAAE,KAAK,EAAE,KAAK,EAAE,IAAI,EAAE,IAAI;IAO1D,IAAI,QAAO,SAAS,CAwBnB;IAGD,QAAQ,CAAC,QAAQ,GAAI,WAAW,SAAS,UAExC;IAGD,QAAQ,CAAC,OAAO,GAAI,WAAW,SAAS,UAEvC;IAGD,QAAQ,CAAC,MAAM,GAAI,WAAW,SAAS,UAItC;IAGD,QAAQ,CAAC,MAAM,GAAI,WAAW,SAAS,EAAE,SAAS,OAAO,CAAC,IAAI,CAAC,UAO9D;IAGD,QAAQ,CAAC,QAAQ,GAAI,WAAW,SAAS,GAAG,MAAM,UAEjD;IAGD,QAAQ,CAAC,QAAQ,GAAI,WAAW,SAAS,GAAG,MAAM,UAEjD;IAGD,QAAQ,CAAC,KAAK,GAAI,WAAW,SAAS,GAAG,MAAM,UAE9C;CAWF"}
@@ -0,0 +1,8 @@
1
+ export interface Meta {
2
+ displayName: string;
3
+ description?: string;
4
+ package: string;
5
+ group?: string;
6
+ additional?: Record<string, any>;
7
+ }
8
+ //# sourceMappingURL=meta.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"meta.d.ts","sourceRoot":"","sources":["../../src/inspector/meta.ts"],"names":[],"mappings":"AACA,MAAM,WAAW,IAAI;IAEnB,WAAW,EAAE,MAAM,CAAA;IAGnB,WAAW,CAAC,EAAE,MAAM,CAAA;IAGpB,OAAO,EAAE,MAAM,CAAA;IAGf,KAAK,CAAC,EAAE,MAAM,CAAA;IAGd,UAAU,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAA;CACjC"}
@@ -0,0 +1,26 @@
1
+ import type { Container, Slice, SliceType } from '../context';
2
+ import type { Meta } from '../inspector';
3
+ import type { Clock, TimerType } from '../timer';
4
+ import { Inspector } from '../inspector';
5
+ export declare class Ctx {
6
+ #private;
7
+ constructor(container: Container, clock: Clock, meta?: Meta);
8
+ get meta(): Meta | undefined;
9
+ get inspector(): Inspector | undefined;
10
+ readonly produce: (meta?: Meta) => Ctx;
11
+ readonly inject: <T>(sliceType: SliceType<T>, value?: T) => this;
12
+ readonly remove: <T, N extends string = string>(sliceType: SliceType<T, N> | N) => this;
13
+ readonly record: (timerType: TimerType) => this;
14
+ readonly clearTimer: (timerType: TimerType) => this;
15
+ readonly isInjected: <T, N extends string = string>(sliceType: SliceType<T, N> | N) => boolean;
16
+ readonly isRecorded: (timerType: TimerType) => boolean;
17
+ readonly use: <T, N extends string = string>(sliceType: SliceType<T, N> | N) => Slice<T, N>;
18
+ readonly get: <T, N extends string>(sliceType: SliceType<T, N> | N) => T;
19
+ readonly set: <T, N extends string>(sliceType: SliceType<T, N> | N, value: T) => void;
20
+ readonly update: <T, N extends string>(sliceType: SliceType<T, N> | N, updater: (prev: T) => T) => void;
21
+ readonly timer: (timer: TimerType) => import("..").Timer;
22
+ readonly done: (timer: TimerType) => void;
23
+ readonly wait: (timer: TimerType) => Promise<void>;
24
+ readonly waitTimers: (slice: SliceType<TimerType[]>) => Promise<void>;
25
+ }
26
+ //# sourceMappingURL=ctx.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ctx.d.ts","sourceRoot":"","sources":["../../src/plugin/ctx.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,KAAK,EAAE,SAAS,EAAE,MAAM,YAAY,CAAA;AAC7D,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,cAAc,CAAA;AACxC,OAAO,KAAK,EAAE,KAAK,EAAE,SAAS,EAAE,MAAM,UAAU,CAAA;AAEhD,OAAO,EAAE,SAAS,EAAE,MAAM,cAAc,CAAA;AAGxC,qBAAa,GAAG;;gBAWF,SAAS,EAAE,SAAS,EAAE,KAAK,EAAE,KAAK,EAAE,IAAI,CAAC,EAAE,IAAI;IAQ3D,IAAI,IAAI,qBAEP;IAGD,IAAI,SAAS,0BAEZ;IAKD,QAAQ,CAAC,OAAO,GAAI,OAAO,IAAI,SAK9B;IAGD,QAAQ,CAAC,MAAM,GAAI,CAAC,EAAE,WAAW,SAAS,CAAC,CAAC,CAAC,EAAE,QAAQ,CAAC,UAOvD;IAGD,QAAQ,CAAC,MAAM,GAAI,CAAC,EAAE,CAAC,SAAS,MAAM,GAAG,MAAM,EAC7C,WAAW,SAAS,CAAC,CAAC,EAAE,CAAC,CAAC,GAAG,CAAC,UAK/B;IAGD,QAAQ,CAAC,MAAM,GAAI,WAAW,SAAS,UAItC;IAGD,QAAQ,CAAC,UAAU,GAAI,WAAW,SAAS,UAI1C;IAGD,QAAQ,CAAC,UAAU,GAAI,CAAC,EAAE,CAAC,SAAS,MAAM,GAAG,MAAM,EACjD,WAAW,SAAS,CAAC,CAAC,EAAE,CAAC,CAAC,GAAG,CAAC,aACG;IAGnC,QAAQ,CAAC,UAAU,GAAI,WAAW,SAAS,aAA+B;IAG1E,QAAQ,CAAC,GAAG,GAAI,CAAC,EAAE,CAAC,SAAS,MAAM,GAAG,MAAM,EAC1C,WAAW,SAAS,CAAC,CAAC,EAAE,CAAC,CAAC,GAAG,CAAC,KAC7B,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAGb;IAGD,QAAQ,CAAC,GAAG,GAAI,CAAC,EAAE,CAAC,SAAS,MAAM,EAAE,WAAW,SAAS,CAAC,CAAC,EAAE,CAAC,CAAC,GAAG,CAAC,OACxC;IAG3B,QAAQ,CAAC,GAAG,GAAI,CAAC,EAAE,CAAC,SAAS,MAAM,EACjC,WAAW,SAAS,CAAC,CAAC,EAAE,CAAC,CAAC,GAAG,CAAC,EAC9B,OAAO,CAAC,UACyB;IAGnC,QAAQ,CAAC,MAAM,GAAI,CAAC,EAAE,CAAC,SAAS,MAAM,EACpC,WAAW,SAAS,CAAC,CAAC,EAAE,CAAC,CAAC,GAAG,CAAC,EAC9B,SAAS,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC,UACe;IAGxC,QAAQ,CAAC,KAAK,GAAI,OAAO,SAAS,wBAA2B;IAG7D,QAAQ,CAAC,IAAI,GAAI,OAAO,SAAS,UAGhC;IAGD,QAAQ,CAAC,IAAI,GAAI,OAAO,SAAS,mBAIhC;IAQD,QAAQ,CAAC,UAAU,GAAU,OAAO,SAAS,CAAC,SAAS,EAAE,CAAC,mBAEzD;CACF"}
@@ -0,0 +1,3 @@
1
+ export * from './ctx';
2
+ export * from './types';
3
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/plugin/index.ts"],"names":[],"mappings":"AAAA,cAAc,OAAO,CAAA;AACrB,cAAc,SAAS,CAAA"}
@@ -0,0 +1,9 @@
1
+ import type { Meta } from '../inspector';
2
+ import type { Ctx } from './ctx';
3
+ export type Cleanup = () => void | Promise<void>;
4
+ export type RunnerReturnType = void | Promise<void> | Cleanup | Promise<Cleanup>;
5
+ export type CtxRunner = () => RunnerReturnType;
6
+ export type MilkdownPlugin = {
7
+ meta?: Meta;
8
+ } & ((ctx: Ctx) => CtxRunner);
9
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/plugin/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,cAAc,CAAA;AACxC,OAAO,KAAK,EAAE,GAAG,EAAE,MAAM,OAAO,CAAA;AAGhC,MAAM,MAAM,OAAO,GAAG,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAA;AAGhD,MAAM,MAAM,gBAAgB,GAAG,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,GAAG,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC,CAAA;AAGhF,MAAM,MAAM,SAAS,GAAG,MAAM,gBAAgB,CAAA;AAgC9C,MAAM,MAAM,cAAc,GAAG;IAAE,IAAI,CAAC,EAAE,IAAI,CAAA;CAAE,GAAG,CAAC,CAAC,GAAG,EAAE,GAAG,KAAK,SAAS,CAAC,CAAA"}
@@ -0,0 +1,9 @@
1
+ import type { Timer, TimerType } from './timer';
2
+ export type TimerMap = Map<symbol, Timer>;
3
+ export declare class Clock {
4
+ readonly store: TimerMap;
5
+ get: (timer: TimerType) => Timer;
6
+ remove: (timer: TimerType) => void;
7
+ has: (timer: TimerType) => boolean;
8
+ }
9
+ //# sourceMappingURL=clock.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"clock.d.ts","sourceRoot":"","sources":["../../src/timer/clock.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,KAAK,EAAE,SAAS,EAAE,MAAM,SAAS,CAAA;AAG/C,MAAM,MAAM,QAAQ,GAAG,GAAG,CAAC,MAAM,EAAE,KAAK,CAAC,CAAA;AAGzC,qBAAa,KAAK;IAEhB,QAAQ,CAAC,KAAK,EAAE,QAAQ,CAAY;IAGpC,GAAG,GAAI,OAAO,SAAS,WAItB;IAGD,MAAM,GAAI,OAAO,SAAS,UAEzB;IAGD,GAAG,GAAI,OAAO,SAAS,aAEtB;CACF"}
@@ -0,0 +1,3 @@
1
+ export * from './clock';
2
+ export * from './timer';
3
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/timer/index.ts"],"names":[],"mappings":"AAAA,cAAc,SAAS,CAAA;AACvB,cAAc,SAAS,CAAA"}
@@ -0,0 +1,19 @@
1
+ import type { TimerMap } from './clock';
2
+ export type TimerStatus = 'pending' | 'resolved' | 'rejected';
3
+ export declare class Timer {
4
+ #private;
5
+ readonly type: TimerType;
6
+ constructor(clock: TimerMap, type: TimerType);
7
+ get status(): TimerStatus;
8
+ start: () => Promise<void>;
9
+ done: () => void;
10
+ }
11
+ export declare class TimerType {
12
+ readonly id: symbol;
13
+ readonly name: string;
14
+ readonly timeout: number;
15
+ constructor(name: string, timeout?: number);
16
+ create: (clock: TimerMap) => Timer;
17
+ }
18
+ export declare const createTimer: (name: string, timeout?: number) => TimerType;
19
+ //# sourceMappingURL=timer.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"timer.d.ts","sourceRoot":"","sources":["../../src/timer/timer.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAA;AAEvC,MAAM,MAAM,WAAW,GAAG,SAAS,GAAG,UAAU,GAAG,UAAU,CAAA;AAG7D,qBAAa,KAAK;;IAEhB,QAAQ,CAAC,IAAI,EAAE,SAAS,CAAA;gBAYZ,KAAK,EAAE,QAAQ,EAAE,IAAI,EAAE,SAAS;IAQ5C,IAAI,MAAM,gBAET;IAKD,KAAK,sBAyBJ;IAGD,IAAI,aAKH;CAaF;AAGD,qBAAa,SAAS;IAEpB,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAA;IAEnB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;IAErB,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAA;gBAIZ,IAAI,EAAE,MAAM,EAAE,OAAO,SAAO;IAOxC,MAAM,GAAI,OAAO,QAAQ,KAAG,KAAK,CAEhC;CACF;AAID,eAAO,MAAM,WAAW,GAAI,MAAM,MAAM,EAAE,gBAAc,cAC1B,CAAA"}