@fluxmail/core 0.21.0 → 0.22.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/errors.d.ts +2 -2
- package/dist/errors.d.ts.map +1 -1
- package/dist/errors.js +15 -3
- package/dist/errors.js.map +1 -1
- package/dist/mcp/tools.d.ts.map +1 -1
- package/dist/mcp/tools.generated.d.ts.map +1 -1
- package/dist/mcp/tools.generated.js +72 -4
- package/dist/mcp/tools.generated.js.map +1 -1
- package/dist/mcp/tools.js +6 -3
- package/dist/mcp/tools.js.map +1 -1
- package/dist/provider.d.ts +7 -0
- package/dist/provider.d.ts.map +1 -1
- package/dist/quotedHtml.d.ts +12 -0
- package/dist/quotedHtml.d.ts.map +1 -0
- package/dist/quotedHtml.js +324 -0
- package/dist/quotedHtml.js.map +1 -0
- package/dist/reply.d.ts +44 -3
- package/dist/reply.d.ts.map +1 -1
- package/dist/reply.js +277 -13
- package/dist/reply.js.map +1 -1
- package/package.json +4 -1
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Whether `html` would nest deeper than `limit`, in one linear pass. An end tag closes the nearest
|
|
3
|
+
* open element of its name and everything inside it, and one that names no open element is ignored,
|
|
4
|
+
* as a parser does. Tags inside comments and attributes count too, so this can only overestimate.
|
|
5
|
+
*/
|
|
6
|
+
export declare function exceedsNestingDepth(html: string, limit?: number): boolean;
|
|
7
|
+
/**
|
|
8
|
+
* The original's HTML reduced to safe formatting, with every element it opens closed again, or
|
|
9
|
+
* undefined when it nests too deeply to parse safely.
|
|
10
|
+
*/
|
|
11
|
+
export declare function sanitizeQuotedHtml(html: string): string | undefined;
|
|
12
|
+
//# sourceMappingURL=quotedHtml.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"quotedHtml.d.ts","sourceRoot":"","sources":["../src/quotedHtml.ts"],"names":[],"mappings":"AA6PA;;;;GAIG;AACH,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,SAAoB,GAAG,OAAO,CAoBpF;AAED;;;GAGG;AACH,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAoCnE"}
|
|
@@ -0,0 +1,324 @@
|
|
|
1
|
+
import { Parser } from 'htmlparser2';
|
|
2
|
+
// Mail Fluxmail quotes or forwards comes from other people, so its HTML is rebuilt from an allowlist before
|
|
3
|
+
// it goes out under the user's name. Tags are balanced, so the original can't close the quote and put text
|
|
4
|
+
// outside it, and nothing in it can run, load a document or restyle the rest of the message.
|
|
5
|
+
const ALLOWED_TAGS = new Set([
|
|
6
|
+
'a',
|
|
7
|
+
'abbr',
|
|
8
|
+
'address',
|
|
9
|
+
'b',
|
|
10
|
+
'bdi',
|
|
11
|
+
'bdo',
|
|
12
|
+
'big',
|
|
13
|
+
'blockquote',
|
|
14
|
+
'br',
|
|
15
|
+
'caption',
|
|
16
|
+
'center',
|
|
17
|
+
'cite',
|
|
18
|
+
'code',
|
|
19
|
+
'col',
|
|
20
|
+
'colgroup',
|
|
21
|
+
'dd',
|
|
22
|
+
'del',
|
|
23
|
+
'dfn',
|
|
24
|
+
'div',
|
|
25
|
+
'dl',
|
|
26
|
+
'dt',
|
|
27
|
+
'em',
|
|
28
|
+
'figcaption',
|
|
29
|
+
'figure',
|
|
30
|
+
'font',
|
|
31
|
+
'h1',
|
|
32
|
+
'h2',
|
|
33
|
+
'h3',
|
|
34
|
+
'h4',
|
|
35
|
+
'h5',
|
|
36
|
+
'h6',
|
|
37
|
+
'hr',
|
|
38
|
+
'i',
|
|
39
|
+
'img',
|
|
40
|
+
'ins',
|
|
41
|
+
'kbd',
|
|
42
|
+
'li',
|
|
43
|
+
'mark',
|
|
44
|
+
'ol',
|
|
45
|
+
'p',
|
|
46
|
+
'pre',
|
|
47
|
+
'q',
|
|
48
|
+
's',
|
|
49
|
+
'samp',
|
|
50
|
+
'small',
|
|
51
|
+
'span',
|
|
52
|
+
'strike',
|
|
53
|
+
'strong',
|
|
54
|
+
'sub',
|
|
55
|
+
'sup',
|
|
56
|
+
'table',
|
|
57
|
+
'tbody',
|
|
58
|
+
'td',
|
|
59
|
+
'tfoot',
|
|
60
|
+
'th',
|
|
61
|
+
'thead',
|
|
62
|
+
'time',
|
|
63
|
+
'tr',
|
|
64
|
+
'tt',
|
|
65
|
+
'u',
|
|
66
|
+
'ul',
|
|
67
|
+
'var',
|
|
68
|
+
'wbr',
|
|
69
|
+
]);
|
|
70
|
+
const VOID_TAGS = new Set(['br', 'col', 'hr', 'img', 'wbr']);
|
|
71
|
+
// Content of these elements is dropped along with the tags.
|
|
72
|
+
const DROPPED_WITH_CONTENT = new Set([
|
|
73
|
+
'applet',
|
|
74
|
+
'audio',
|
|
75
|
+
'embed',
|
|
76
|
+
'frame',
|
|
77
|
+
'frameset',
|
|
78
|
+
'head',
|
|
79
|
+
'iframe',
|
|
80
|
+
'math',
|
|
81
|
+
'noembed',
|
|
82
|
+
'noframes',
|
|
83
|
+
'noscript',
|
|
84
|
+
'object',
|
|
85
|
+
'script',
|
|
86
|
+
'select',
|
|
87
|
+
'style',
|
|
88
|
+
'svg',
|
|
89
|
+
'template',
|
|
90
|
+
'textarea',
|
|
91
|
+
'title',
|
|
92
|
+
'video',
|
|
93
|
+
]);
|
|
94
|
+
const ALLOWED_ATTRIBUTES = new Set([
|
|
95
|
+
'align',
|
|
96
|
+
'alt',
|
|
97
|
+
'bgcolor',
|
|
98
|
+
'border',
|
|
99
|
+
'cellpadding',
|
|
100
|
+
'cellspacing',
|
|
101
|
+
'color',
|
|
102
|
+
'colspan',
|
|
103
|
+
'dir',
|
|
104
|
+
'face',
|
|
105
|
+
'height',
|
|
106
|
+
'href',
|
|
107
|
+
'lang',
|
|
108
|
+
'rowspan',
|
|
109
|
+
'size',
|
|
110
|
+
'src',
|
|
111
|
+
'style',
|
|
112
|
+
'title',
|
|
113
|
+
'valign',
|
|
114
|
+
'width',
|
|
115
|
+
]);
|
|
116
|
+
// Style properties that could move quoted content over the user's reply or load something.
|
|
117
|
+
// Formatting properties a quote may keep. Anything that could move the quote over the reply, such as
|
|
118
|
+
// position, transform or a negative margin, is left out.
|
|
119
|
+
const ALLOWED_STYLE = new Set([
|
|
120
|
+
'background-color',
|
|
121
|
+
'border-collapse',
|
|
122
|
+
'border-radius',
|
|
123
|
+
'border-spacing',
|
|
124
|
+
'color',
|
|
125
|
+
'direction',
|
|
126
|
+
'display',
|
|
127
|
+
'font',
|
|
128
|
+
'font-family',
|
|
129
|
+
'font-size',
|
|
130
|
+
'font-style',
|
|
131
|
+
'font-variant',
|
|
132
|
+
'font-weight',
|
|
133
|
+
'height',
|
|
134
|
+
'letter-spacing',
|
|
135
|
+
'line-height',
|
|
136
|
+
'list-style-type',
|
|
137
|
+
'margin',
|
|
138
|
+
'margin-bottom',
|
|
139
|
+
'margin-left',
|
|
140
|
+
'margin-right',
|
|
141
|
+
'margin-top',
|
|
142
|
+
'max-width',
|
|
143
|
+
'min-width',
|
|
144
|
+
'overflow-wrap',
|
|
145
|
+
'padding',
|
|
146
|
+
'padding-bottom',
|
|
147
|
+
'padding-left',
|
|
148
|
+
'padding-right',
|
|
149
|
+
'padding-top',
|
|
150
|
+
'table-layout',
|
|
151
|
+
'text-align',
|
|
152
|
+
'text-decoration',
|
|
153
|
+
'text-transform',
|
|
154
|
+
'vertical-align',
|
|
155
|
+
'white-space',
|
|
156
|
+
'width',
|
|
157
|
+
'word-break',
|
|
158
|
+
'word-wrap',
|
|
159
|
+
]);
|
|
160
|
+
const BORDER_STYLE = /^border(?:-(?:top|right|bottom|left))?(?:-(?:color|style|width))?$/;
|
|
161
|
+
// Color functions are the only CSS functions kept, so calc(), var() and url() can't hide a value.
|
|
162
|
+
const ALLOWED_FUNCTIONS = new Set(['rgb', 'rgba', 'hsl', 'hsla']);
|
|
163
|
+
function escapeText(value) {
|
|
164
|
+
return value.replace(/&/g, '&').replace(/</g, '<').replace(/>/g, '>');
|
|
165
|
+
}
|
|
166
|
+
function escapeAttribute(value) {
|
|
167
|
+
return escapeText(value).replace(/"/g, '"');
|
|
168
|
+
}
|
|
169
|
+
function safeUrl(tag, name, value) {
|
|
170
|
+
const url = value.trim();
|
|
171
|
+
if (name === 'href')
|
|
172
|
+
return /^(?:https?:|mailto:|#)/i.test(url) ? url : undefined;
|
|
173
|
+
if (tag === 'img')
|
|
174
|
+
return /^(?:https?:|cid:|data:image\/(?:png|gif|jpe?g|webp);)/i.test(url) ? url : undefined;
|
|
175
|
+
return undefined;
|
|
176
|
+
}
|
|
177
|
+
function safeDeclaration(declaration) {
|
|
178
|
+
const separator = declaration.indexOf(':');
|
|
179
|
+
if (separator < 1)
|
|
180
|
+
return undefined;
|
|
181
|
+
const property = declaration.slice(0, separator).trim().toLowerCase();
|
|
182
|
+
const value = declaration
|
|
183
|
+
.slice(separator + 1)
|
|
184
|
+
.replace(/!\s*important\s*$/i, '')
|
|
185
|
+
.trim();
|
|
186
|
+
if (!value || (!ALLOWED_STYLE.has(property) && !BORDER_STYLE.test(property)))
|
|
187
|
+
return undefined;
|
|
188
|
+
// Escapes and comments could spell a different property or value than the one checked here.
|
|
189
|
+
if (/[\\]|\/\*/.test(value) || !/^[\w\s#%.,'"/()+-]*$/.test(value))
|
|
190
|
+
return undefined;
|
|
191
|
+
for (const [, name] of value.matchAll(/([\w-]+)\s*\(/g)) {
|
|
192
|
+
if (!ALLOWED_FUNCTIONS.has(name.toLowerCase()))
|
|
193
|
+
return undefined;
|
|
194
|
+
}
|
|
195
|
+
// A negative margin can pull the quote over the reply above it.
|
|
196
|
+
if (property.startsWith('margin') && value.includes('-'))
|
|
197
|
+
return undefined;
|
|
198
|
+
return `${property}:${value}`;
|
|
199
|
+
}
|
|
200
|
+
function safeStyle(value) {
|
|
201
|
+
const declarations = value
|
|
202
|
+
.split(';')
|
|
203
|
+
.map((declaration) => safeDeclaration(declaration))
|
|
204
|
+
.filter((declaration) => declaration !== undefined);
|
|
205
|
+
return declarations.length ? declarations.join('; ') : undefined;
|
|
206
|
+
}
|
|
207
|
+
function attributes(tag, attribs) {
|
|
208
|
+
let out = '';
|
|
209
|
+
for (const [name, value] of Object.entries(attribs)) {
|
|
210
|
+
if (!ALLOWED_ATTRIBUTES.has(name))
|
|
211
|
+
continue;
|
|
212
|
+
const safe = name === 'href' || name === 'src' ? safeUrl(tag, name, value) : name === 'style' ? safeStyle(value) : value;
|
|
213
|
+
if (safe !== undefined)
|
|
214
|
+
out += ` ${name}="${escapeAttribute(safe)}"`;
|
|
215
|
+
}
|
|
216
|
+
return tag === 'a' && attribs.href !== undefined && out.includes(' href=')
|
|
217
|
+
? `${out} target="_blank" rel="noopener noreferrer"`
|
|
218
|
+
: out;
|
|
219
|
+
}
|
|
220
|
+
// Real email nests a few dozen levels. The parser takes quadratic time on deeper nesting, so deeper
|
|
221
|
+
// HTML isn't parsed at all.
|
|
222
|
+
const MAX_NESTING_DEPTH = 500;
|
|
223
|
+
// Elements that never stay open, either void or closed by their next sibling, so they don't add depth.
|
|
224
|
+
const NON_NESTING_TAGS = new Set([
|
|
225
|
+
...VOID_TAGS,
|
|
226
|
+
'area',
|
|
227
|
+
'base',
|
|
228
|
+
'embed',
|
|
229
|
+
'input',
|
|
230
|
+
'link',
|
|
231
|
+
'meta',
|
|
232
|
+
'param',
|
|
233
|
+
'source',
|
|
234
|
+
'track',
|
|
235
|
+
'p',
|
|
236
|
+
'li',
|
|
237
|
+
'dt',
|
|
238
|
+
'dd',
|
|
239
|
+
'td',
|
|
240
|
+
'th',
|
|
241
|
+
'tr',
|
|
242
|
+
'tbody',
|
|
243
|
+
'thead',
|
|
244
|
+
'tfoot',
|
|
245
|
+
'option',
|
|
246
|
+
]);
|
|
247
|
+
/**
|
|
248
|
+
* Whether `html` would nest deeper than `limit`, in one linear pass. An end tag closes the nearest
|
|
249
|
+
* open element of its name and everything inside it, and one that names no open element is ignored,
|
|
250
|
+
* as a parser does. Tags inside comments and attributes count too, so this can only overestimate.
|
|
251
|
+
*/
|
|
252
|
+
export function exceedsNestingDepth(html, limit = MAX_NESTING_DEPTH) {
|
|
253
|
+
const stack = [];
|
|
254
|
+
const open = new Map();
|
|
255
|
+
for (const [, closing, rawName] of html.matchAll(/<(\/?)([a-z][a-z0-9:-]*)/gi)) {
|
|
256
|
+
const name = rawName.toLowerCase();
|
|
257
|
+
if (closing) {
|
|
258
|
+
if (!open.get(name))
|
|
259
|
+
continue;
|
|
260
|
+
let popped;
|
|
261
|
+
do {
|
|
262
|
+
popped = stack.pop();
|
|
263
|
+
open.set(popped, open.get(popped) - 1);
|
|
264
|
+
} while (popped !== name);
|
|
265
|
+
continue;
|
|
266
|
+
}
|
|
267
|
+
if (NON_NESTING_TAGS.has(name))
|
|
268
|
+
continue;
|
|
269
|
+
stack.push(name);
|
|
270
|
+
open.set(name, (open.get(name) ?? 0) + 1);
|
|
271
|
+
if (stack.length > limit)
|
|
272
|
+
return true;
|
|
273
|
+
}
|
|
274
|
+
return false;
|
|
275
|
+
}
|
|
276
|
+
/**
|
|
277
|
+
* The original's HTML reduced to safe formatting, with every element it opens closed again, or
|
|
278
|
+
* undefined when it nests too deeply to parse safely.
|
|
279
|
+
*/
|
|
280
|
+
export function sanitizeQuotedHtml(html) {
|
|
281
|
+
if (exceedsNestingDepth(html))
|
|
282
|
+
return undefined;
|
|
283
|
+
let out = '';
|
|
284
|
+
const open = [];
|
|
285
|
+
let dropping = 0;
|
|
286
|
+
const parser = new Parser({
|
|
287
|
+
onopentag(name, attribs) {
|
|
288
|
+
if (dropping || DROPPED_WITH_CONTENT.has(name)) {
|
|
289
|
+
if (!VOID_TAGS.has(name))
|
|
290
|
+
dropping++;
|
|
291
|
+
return;
|
|
292
|
+
}
|
|
293
|
+
if (!ALLOWED_TAGS.has(name))
|
|
294
|
+
return;
|
|
295
|
+
out += `<${name}${attributes(name, attribs)}>`;
|
|
296
|
+
if (!VOID_TAGS.has(name))
|
|
297
|
+
open.push(name);
|
|
298
|
+
},
|
|
299
|
+
ontext(text) {
|
|
300
|
+
if (!dropping)
|
|
301
|
+
out += escapeText(text);
|
|
302
|
+
},
|
|
303
|
+
onclosetag(name) {
|
|
304
|
+
if (dropping) {
|
|
305
|
+
if (!VOID_TAGS.has(name))
|
|
306
|
+
dropping--;
|
|
307
|
+
return;
|
|
308
|
+
}
|
|
309
|
+
if (VOID_TAGS.has(name) || !ALLOWED_TAGS.has(name))
|
|
310
|
+
return;
|
|
311
|
+
const index = open.lastIndexOf(name);
|
|
312
|
+
if (index === -1)
|
|
313
|
+
return;
|
|
314
|
+
while (open.length > index)
|
|
315
|
+
out += `</${open.pop()}>`;
|
|
316
|
+
},
|
|
317
|
+
}, { decodeEntities: true, lowerCaseTags: true, lowerCaseAttributeNames: true, recognizeSelfClosing: true });
|
|
318
|
+
parser.write(html);
|
|
319
|
+
parser.end();
|
|
320
|
+
while (open.length)
|
|
321
|
+
out += `</${open.pop()}>`;
|
|
322
|
+
return out;
|
|
323
|
+
}
|
|
324
|
+
//# sourceMappingURL=quotedHtml.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"quotedHtml.js","sourceRoot":"","sources":["../src/quotedHtml.ts"],"names":[],"mappings":"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"}
|
package/dist/reply.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { EmailAddress, Message, SendAsIdentity } from './types.js';
|
|
1
|
+
import type { AttachmentInput, AttachmentMeta, EmailAddress, Message, MessageBody, SendAsIdentity } from './types.js';
|
|
2
2
|
export interface ReplyRecipients {
|
|
3
3
|
to: EmailAddress[];
|
|
4
4
|
cc: EmailAddress[];
|
|
@@ -20,9 +20,50 @@ export declare function formatAddressList(addrs: EmailAddress[] | undefined): st
|
|
|
20
20
|
* addressed to, falling back to the primary identity.
|
|
21
21
|
*/
|
|
22
22
|
export declare function selectReplySender(original: Message, identities: SendAsIdentity[]): SendAsIdentity;
|
|
23
|
-
|
|
24
|
-
|
|
23
|
+
export interface ForwardBodyOptions {
|
|
24
|
+
/** IANA time zone for the forwarded message's date. Defaults to UTC. */
|
|
25
|
+
timeZone?: string;
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* The body of a forward, as Gmail writes one: an optional comment, a "Forwarded message" header
|
|
29
|
+
* with the original's sender, date, subject and recipients, then the original's text and sanitized
|
|
30
|
+
* HTML.
|
|
31
|
+
*/
|
|
32
|
+
export declare function buildForwardBody(original: Message, comment?: string, options?: ForwardBodyOptions): {
|
|
25
33
|
text?: string;
|
|
26
34
|
html?: string;
|
|
27
35
|
};
|
|
36
|
+
/** Whether `timeZone` is an IANA time zone name the runtime can format dates in. */
|
|
37
|
+
export declare function isValidTimeZone(timeZone: string): boolean;
|
|
38
|
+
export interface ReplyBodyOptions {
|
|
39
|
+
/** Whether a quoted body is within the caller's size limits. */
|
|
40
|
+
fits?: (body: MessageBody) => boolean;
|
|
41
|
+
/** IANA time zone for the date in the "wrote:" line. Defaults to UTC. */
|
|
42
|
+
timeZone?: string;
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* The body of a reply: the new content, then an "On <date> <sender> wrote:" line, as Gmail writes it,
|
|
46
|
+
* and the quoted original. A plain-text reply to an HTML original also gets an HTML part. Otherwise
|
|
47
|
+
* only the parts the reply has are quoted, and a quote of the same original
|
|
48
|
+
* that Fluxmail added earlier is replaced. The original's HTML is sanitized first. If the quote is
|
|
49
|
+
* too large, the HTML part quotes the original's text instead, then the text is shortened; if even a
|
|
50
|
+
* short quote doesn't fit, the body is returned unquoted.
|
|
51
|
+
*/
|
|
52
|
+
export declare function buildReplyBody(original: Message, body: MessageBody, options?: ReplyBodyOptions): MessageBody;
|
|
53
|
+
export interface QuotedImageOptions {
|
|
54
|
+
/** Attachments the message already has. An image with the same Content-ID isn't added again. */
|
|
55
|
+
attachments?: AttachmentInput[];
|
|
56
|
+
/** Most attachments the message may have in total. */
|
|
57
|
+
maxCount: number;
|
|
58
|
+
/** Most decoded attachment bytes the message may have in total. */
|
|
59
|
+
maxBytes: number;
|
|
60
|
+
/** The attachment's content, or undefined to leave it out, for example because it is over `maxBytes`. */
|
|
61
|
+
download: (attachment: AttachmentMeta, maxBytes: number) => Promise<Uint8Array | undefined>;
|
|
62
|
+
}
|
|
63
|
+
/**
|
|
64
|
+
* The original's attachments that `html` shows through cid: references, such as images embedded in a
|
|
65
|
+
* quoted or forwarded message, ready to send with it. Without them those images show as missing.
|
|
66
|
+
* An image that would go over the limits is left out, so the message still goes out.
|
|
67
|
+
*/
|
|
68
|
+
export declare function quotedImages(original: Message, html: string | undefined, options: QuotedImageOptions): Promise<AttachmentInput[]>;
|
|
28
69
|
//# sourceMappingURL=reply.d.ts.map
|
package/dist/reply.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"reply.d.ts","sourceRoot":"","sources":["../src/reply.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"reply.d.ts","sourceRoot":"","sources":["../src/reply.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,eAAe,EAAE,cAAc,EAAE,YAAY,EAAE,OAAO,EAAE,WAAW,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AAEtH,MAAM,WAAW,eAAe;IAC9B,EAAE,EAAE,YAAY,EAAE,CAAC;IACnB,EAAE,EAAE,YAAY,EAAE,CAAC;CACpB;AAeD;;;;GAIG;AACH,wBAAgB,sBAAsB,CACpC,QAAQ,EAAE,OAAO,EACjB,YAAY,EAAE,MAAM,GAAG,MAAM,EAAE,EAC/B,QAAQ,EAAE,OAAO,GAChB,eAAe,CAejB;AAED,+CAA+C;AAC/C,wBAAgB,YAAY,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAEpD;AAED,gDAAgD;AAChD,wBAAgB,cAAc,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAEtD;AAED,wBAAgB,aAAa,CAAC,CAAC,EAAE,YAAY,GAAG,MAAM,CAErD;AAED,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,YAAY,EAAE,GAAG,SAAS,GAAG,MAAM,CAE3E;AAED;;;GAGG;AACH,wBAAgB,iBAAiB,CAAC,QAAQ,EAAE,OAAO,EAAE,UAAU,EAAE,cAAc,EAAE,GAAG,cAAc,CASjG;AAWD,MAAM,WAAW,kBAAkB;IACjC,wEAAwE;IACxE,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED;;;;GAIG;AACH,wBAAgB,gBAAgB,CAC9B,QAAQ,EAAE,OAAO,EACjB,OAAO,CAAC,EAAE,MAAM,EAChB,OAAO,GAAE,kBAAuB,GAC/B;IAAE,IAAI,CAAC,EAAE,MAAM,CAAC;IAAC,IAAI,CAAC,EAAE,MAAM,CAAA;CAAE,CAkClC;AAED,oFAAoF;AACpF,wBAAgB,eAAe,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAOzD;AA2JD,MAAM,WAAW,gBAAgB;IAC/B,gEAAgE;IAChE,IAAI,CAAC,EAAE,CAAC,IAAI,EAAE,WAAW,KAAK,OAAO,CAAC;IACtC,yEAAyE;IACzE,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED;;;;;;;GAOG;AACH,wBAAgB,cAAc,CAAC,QAAQ,EAAE,OAAO,EAAE,IAAI,EAAE,WAAW,EAAE,OAAO,GAAE,gBAAqB,GAAG,WAAW,CAyDhH;AAED,MAAM,WAAW,kBAAkB;IACjC,gGAAgG;IAChG,WAAW,CAAC,EAAE,eAAe,EAAE,CAAC;IAChC,sDAAsD;IACtD,QAAQ,EAAE,MAAM,CAAC;IACjB,mEAAmE;IACnE,QAAQ,EAAE,MAAM,CAAC;IACjB,yGAAyG;IACzG,QAAQ,EAAE,CAAC,UAAU,EAAE,cAAc,EAAE,QAAQ,EAAE,MAAM,KAAK,OAAO,CAAC,UAAU,GAAG,SAAS,CAAC,CAAC;CAC7F;AAED;;;;GAIG;AACH,wBAAsB,YAAY,CAChC,QAAQ,EAAE,OAAO,EACjB,IAAI,EAAE,MAAM,GAAG,SAAS,EACxB,OAAO,EAAE,kBAAkB,GAC1B,OAAO,CAAC,eAAe,EAAE,CAAC,CA0B5B"}
|