@social-mail/shared 1.0.29 → 1.1.4

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 (116) hide show
  1. package/.gitlab-ci.yml +3 -3
  2. package/.vscode/settings.json +1 -1
  3. package/dist/.tsbuildinfo +1 -0
  4. package/dist/QueryIterator.d.ts +1 -9
  5. package/dist/QueryIterator.d.ts.map +1 -1
  6. package/dist/QueryIterator.js +3 -14
  7. package/dist/QueryIterator.js.map +1 -1
  8. package/dist/ical-parser/Calender.js +36 -92
  9. package/dist/ical-parser/Calender.js.map +1 -1
  10. package/dist/ical-parser/parseDate.js +1 -5
  11. package/dist/ical-parser/parseDate.js.map +1 -1
  12. package/dist/mime-parser/AttachmentFile.d.ts +5 -11
  13. package/dist/mime-parser/AttachmentFile.d.ts.map +1 -1
  14. package/dist/mime-parser/AttachmentFile.js +3 -8
  15. package/dist/mime-parser/AttachmentFile.js.map +1 -1
  16. package/dist/mime-parser/HeaderContactList.d.ts +15 -0
  17. package/dist/mime-parser/HeaderContactList.d.ts.map +1 -0
  18. package/dist/mime-parser/HeaderContactList.js +37 -0
  19. package/dist/mime-parser/HeaderContactList.js.map +1 -0
  20. package/dist/mime-parser/HeaderContentDisposition.d.ts +6 -6
  21. package/dist/mime-parser/HeaderContentDisposition.d.ts.map +1 -1
  22. package/dist/mime-parser/HeaderContentDisposition.js +5 -10
  23. package/dist/mime-parser/HeaderContentDisposition.js.map +1 -1
  24. package/dist/mime-parser/HeaderContentType.d.ts +6 -6
  25. package/dist/mime-parser/HeaderContentType.d.ts.map +1 -1
  26. package/dist/mime-parser/HeaderContentType.js +5 -10
  27. package/dist/mime-parser/HeaderContentType.js.map +1 -1
  28. package/dist/mime-parser/HeaderEmailAddress.d.ts +10 -0
  29. package/dist/mime-parser/HeaderEmailAddress.d.ts.map +1 -0
  30. package/dist/mime-parser/HeaderEmailAddress.js +27 -0
  31. package/dist/mime-parser/HeaderEmailAddress.js.map +1 -0
  32. package/dist/mime-parser/HeaderLinks.d.ts +9 -0
  33. package/dist/mime-parser/HeaderLinks.d.ts.map +1 -0
  34. package/dist/mime-parser/HeaderLinks.js +42 -0
  35. package/dist/mime-parser/HeaderLinks.js.map +1 -0
  36. package/dist/mime-parser/MimeEmailAddressParser.d.ts +13 -0
  37. package/dist/mime-parser/MimeEmailAddressParser.d.ts.map +1 -0
  38. package/dist/mime-parser/MimeEmailAddressParser.js +17 -0
  39. package/dist/mime-parser/MimeEmailAddressParser.js.map +1 -0
  40. package/dist/mime-parser/MimeHeaders.d.ts +19 -0
  41. package/dist/mime-parser/MimeHeaders.d.ts.map +1 -0
  42. package/dist/mime-parser/MimeHeaders.js +47 -0
  43. package/dist/mime-parser/MimeHeaders.js.map +1 -0
  44. package/dist/mime-parser/MimeMessage.d.ts +44 -11
  45. package/dist/mime-parser/MimeMessage.d.ts.map +1 -1
  46. package/dist/mime-parser/MimeMessage.js +81 -73
  47. package/dist/mime-parser/MimeMessage.js.map +1 -1
  48. package/dist/mime-parser/MimeNode.d.ts +32 -39
  49. package/dist/mime-parser/MimeNode.d.ts.map +1 -1
  50. package/dist/mime-parser/MimeNode.js +166 -298
  51. package/dist/mime-parser/MimeNode.js.map +1 -1
  52. package/dist/mime-parser/RegexGenerator.d.ts +9 -0
  53. package/dist/mime-parser/RegexGenerator.d.ts.map +1 -0
  54. package/dist/mime-parser/RegexGenerator.js +40 -0
  55. package/dist/mime-parser/RegexGenerator.js.map +1 -0
  56. package/dist/mime-parser/encoder/RawBuffer.d.ts +5 -5
  57. package/dist/mime-parser/encoder/RawBuffer.d.ts.map +1 -1
  58. package/dist/mime-parser/encoder/RawBuffer.js +7 -13
  59. package/dist/mime-parser/encoder/RawBuffer.js.map +1 -1
  60. package/dist/mime-parser/encoder/base64-to-blob.d.ts +1 -7
  61. package/dist/mime-parser/encoder/base64-to-blob.d.ts.map +1 -1
  62. package/dist/mime-parser/encoder/base64-to-blob.js +0 -6
  63. package/dist/mime-parser/encoder/base64-to-blob.js.map +1 -1
  64. package/dist/mime-parser/encoder/quoted-printable.d.ts +5 -8
  65. package/dist/mime-parser/encoder/quoted-printable.d.ts.map +1 -1
  66. package/dist/mime-parser/encoder/quoted-printable.js +3 -34
  67. package/dist/mime-parser/encoder/quoted-printable.js.map +1 -1
  68. package/dist/mime-parser/encoder/word-encoding.d.ts +4 -6
  69. package/dist/mime-parser/encoder/word-encoding.d.ts.map +1 -1
  70. package/dist/mime-parser/encoder/word-encoding.js +4 -5
  71. package/dist/mime-parser/encoder/word-encoding.js.map +1 -1
  72. package/dist/mime-parser/parsePairs.d.ts +1 -1
  73. package/dist/mime-parser/parsePairs.d.ts.map +1 -1
  74. package/dist/mime-parser/parsePairs.js +3 -7
  75. package/dist/mime-parser/parsePairs.js.map +1 -1
  76. package/dist/mime-parser/stream/LineStream.d.ts +10 -16
  77. package/dist/mime-parser/stream/LineStream.d.ts.map +1 -1
  78. package/dist/mime-parser/stream/LineStream.js +59 -94
  79. package/dist/mime-parser/stream/LineStream.js.map +1 -1
  80. package/dist/mime-parser/stream/TextWriter.d.ts +5 -3
  81. package/dist/mime-parser/stream/TextWriter.d.ts.map +1 -1
  82. package/dist/mime-parser/stream/TextWriter.js +15 -3
  83. package/dist/mime-parser/stream/TextWriter.js.map +1 -1
  84. package/dist/mime-parser/tokenizer.d.ts +3 -3
  85. package/dist/mime-parser/tokenizer.d.ts.map +1 -1
  86. package/dist/mime-parser/tokenizer.js +10 -17
  87. package/dist/mime-parser/tokenizer.js.map +1 -1
  88. package/package.json +3 -3
  89. package/src/{QueryIterator.js → QueryIterator.ts} +11 -12
  90. package/src/ical-parser/Calender.ts +1 -1
  91. package/src/mime-parser/AttachmentFile.ts +24 -0
  92. package/src/mime-parser/HeaderContactList.ts +41 -0
  93. package/src/mime-parser/HeaderContentDisposition.ts +21 -0
  94. package/src/mime-parser/HeaderContentType.ts +22 -0
  95. package/src/mime-parser/HeaderEmailAddress.ts +38 -0
  96. package/src/mime-parser/HeaderLinks.ts +48 -0
  97. package/src/mime-parser/MimeEmailAddressParser.ts +22 -0
  98. package/src/mime-parser/MimeHeaders.ts +62 -0
  99. package/src/mime-parser/MimeMessage.ts +134 -0
  100. package/src/mime-parser/{MimeNode.js → MimeNode.ts} +92 -159
  101. package/src/mime-parser/RegexGenerator.ts +42 -0
  102. package/src/mime-parser/encoder/{RawBuffer.js → RawBuffer.ts} +15 -17
  103. package/src/mime-parser/encoder/{base64-to-blob.js → base64-to-blob.ts} +8 -8
  104. package/src/mime-parser/encoder/{quoted-printable.js → quoted-printable.ts} +9 -11
  105. package/src/mime-parser/encoder/{word-encoding.js → word-encoding.ts} +6 -6
  106. package/src/mime-parser/{parsePairs.js → parsePairs.ts} +5 -4
  107. package/src/mime-parser/stream/{LineStream.js → LineStream.ts} +12 -19
  108. package/src/mime-parser/stream/TextWriter.ts +36 -0
  109. package/src/mime-parser/{tokenizer.js → tokenizer.ts} +24 -21
  110. package/tsconfig.json +30 -9
  111. package/dist/tsconfig.tsbuildinfo +0 -1
  112. package/src/mime-parser/AttachmentFile.js +0 -29
  113. package/src/mime-parser/HeaderContentDisposition.js +0 -32
  114. package/src/mime-parser/HeaderContentType.js +0 -34
  115. package/src/mime-parser/MimeMessage.js +0 -105
  116. package/src/mime-parser/stream/TextWriter.js +0 -27
@@ -1,4 +1,3 @@
1
- /* eslint-disable @typescript-eslint/no-redundant-type-constituents */
2
1
  // import QueryIterator from "../../common/QueryIterator";
3
2
  import { AttachmentFile } from "./AttachmentFile.js";
4
3
  import { HeaderContentType } from "./HeaderContentType.js";
@@ -9,32 +8,15 @@ import { quotedPrintable } from "./encoder/quoted-printable.js";
9
8
  import { wordEncoding } from "./encoder/word-encoding.js";
10
9
  import LineStream from "./stream/LineStream.js";
11
10
  import TextWriter from "./stream/TextWriter.js";
11
+ import MimeHeaders from "./MimeHeaders.js";
12
12
 
13
- // export interface IContentTypeObject {
14
- // type: string;
15
- // boundary?: string;
16
- // charset?: string
17
- // };
13
+ export class CIMap extends Map<string, any> {
14
+ private ci = new Map<string, string>();
18
15
 
19
- // export type IContentType = string | IContentTypeObject;
20
-
21
- // export interface IContentDispositionObject {
22
- // type: string;
23
- // filename?: string;
24
- // };
25
-
26
- // export type IContentDisposition = string | IContentDispositionObject;
27
-
28
-
29
-
30
- export class CIMap extends Map {
31
-
32
- ci = new Map();
33
-
34
- set(key, value) {
16
+ set(key: string, value: any): this {
35
17
  if (typeof key === "string") {
36
18
  let ck = this.ci.get(key);
37
- if (ck === void 0) {
19
+ if (ck === undefined) {
38
20
  ck = key.toLocaleLowerCase();
39
21
  this.ci.set(ck, key);
40
22
  } else {
@@ -44,26 +26,29 @@ export class CIMap extends Map {
44
26
  return super.set(key, value);
45
27
  }
46
28
 
47
- get(key) {
29
+ get(key: string): any {
48
30
  if (typeof key === "string") {
49
31
  const ck = key.toLocaleLowerCase();
50
- key = this.ci.get(ck);
32
+ key = this.ci.get(ck) || key;
51
33
  }
52
34
  return super.get(key);
53
35
  }
54
-
55
36
  }
56
37
 
57
-
58
38
  export class MimeNode {
59
-
60
39
  static createMessage({
61
40
  html,
62
41
  subject,
63
42
  text = "",
64
43
  name = "",
65
44
  attachments = []
66
- }) {
45
+ }: {
46
+ html?: string;
47
+ subject: string;
48
+ text?: string;
49
+ name?: string;
50
+ attachments?: any[];
51
+ }): MimeNode {
67
52
  const root = new MimeNode("multipart/mixed");
68
53
  root.setHeader("Subject", subject);
69
54
  if (name) {
@@ -87,11 +72,12 @@ export class MimeNode {
87
72
  }
88
73
 
89
74
  static create(
90
- /** @type {string | File} */ text,
91
- /** @type {string} */ type,
92
- /** @type {string} */id) {
75
+ text: string | File,
76
+ type?: string,
77
+ id?: string
78
+ ): MimeNode {
93
79
  if (typeof text === "string") {
94
- const node = new MimeNode(type);
80
+ const node = new MimeNode(type || "");
95
81
  node.text = text;
96
82
  return node;
97
83
  }
@@ -106,23 +92,36 @@ export class MimeNode {
106
92
  return fileNode;
107
93
  }
108
94
 
109
- /** @type {string} */ encoded;
95
+ encoded?: string;
96
+ children?: MimeNode[];
97
+ get contentType() {
98
+ return this.headers.first("content-type").as(HeaderContentType);
99
+ }
100
+ get contentDisposition() {
101
+ return this.headers.first("content-disposition")?.as(HeaderContentDisposition);
102
+ }
110
103
 
111
- /** @type {MimeNode[]} */ children;
104
+ set contentDisposition(v: HeaderContentDisposition) {
105
+ this.headers.set("content-disposition", v.toString());
106
+ }
112
107
 
113
- /** @type {HeaderContentType} */ contentType;
108
+ textContent?: string;
109
+ blobData?: Blob;
110
+ headers: MimeHeaders;
114
111
 
115
- /** @type {HeaderContentDisposition} */ contentDisposition;
112
+ constructor(type?: string) {
113
+ this.headers = new MimeHeaders();
114
+ this.headers.append("Content-Type", type);
115
+ }
116
116
 
117
- /** @returns {string} */
118
- get text() {
117
+ get text(): string {
119
118
  let tc = this.textContent;
120
119
  if (tc) {
121
120
  return tc;
122
121
  }
123
122
  let { encoded } = this;
124
123
  if (!encoded) {
125
- return;
124
+ return "";
126
125
  }
127
126
  // we need to convert byte array to utf8
128
127
  const cte = this.contentTransferEncoding?.toLowerCase();
@@ -145,118 +144,69 @@ export class MimeNode {
145
144
  return tc;
146
145
  }
147
146
 
148
- set text( /** @type {string} */ v) {
147
+ set text(v: string) {
149
148
  this.contentTransferEncoding = "quoted-printable";
150
149
  this.textContent = v;
151
150
  }
152
151
 
153
- /** @returns {Blob} */
154
- get blob() {
152
+ get blob(): Blob {
155
153
  // this will create blob..
156
154
  if (this.contentTransferEncoding?.toLocaleLowerCase() !== "base64") {
157
155
  throw new Error("Not supported");
158
156
  }
159
- return this.blobData ??= base64toBlob(this.encoded, this.contentType.type);
157
+ return this.blobData ??= base64toBlob(this.encoded!, this.contentType.type);
160
158
  }
161
159
 
162
- set blob( /** @type {Blob} */ v) {
160
+ set blob(v: Blob) {
163
161
  this.blobData = v;
164
162
  }
165
163
 
166
- /** @returns {string} */
167
- get contentTransferEncoding() {
168
- return this.header("Content-Transfer-Encoding");
164
+ get contentTransferEncoding(): string | undefined {
165
+ return this.firstHeaderString("Content-Transfer-Encoding");
169
166
  }
170
167
 
171
- set contentTransferEncoding( /** @type {string} */ v) {
172
- this.setHeader("Content-Transfer-Encoding", v);
168
+ set contentTransferEncoding(v: string | undefined) {
169
+ this.headers.set("Content-Transfer-Encoding", v);
173
170
  }
174
171
 
175
- /** @returns {string} */
176
- get boundary() {
172
+ get boundary(): string | undefined {
177
173
  return this.contentType.boundary;
178
174
  }
179
175
 
180
- /** @returns {IterableIterator<MimeNode>} */
181
- get descendent() {
176
+ get descendent(): IterableIterator<MimeNode> {
182
177
  return this.enumerate();
183
178
  }
184
179
 
185
- /** @type {Blob} */ blobData;
186
- /** @type {string} */ textContent;
187
-
188
- /** @type {Map<string, string | any>} */ headers;
189
-
190
- constructor( /** @type {string} */ type) {
191
- this.headers = new CIMap();
192
- this.contentType = new HeaderContentType(type);
193
- this.headers.set("Content-Type", this.contentType);
194
- }
195
-
196
- getFirstChild(
197
- /** @type {string} */ contentType,
198
- create = false
199
- ) {
200
- contentType = contentType.toLocaleLowerCase();
201
- let child = QueryIterator.first(this.descendent, (x) => x.contentType.type === contentType);
202
- if (!child && create) {
203
- child = new MimeNode(contentType);
204
- (this.children ??= []).push(child);
205
- }
206
- return child;
180
+ firstHeaderString(name: string): any {
181
+ return this.headers.first(name)?.value;
207
182
  }
208
183
 
209
- header(/** @type {string} */ name) {
210
- return this.headers.get(name);
184
+ firstHeaderObject(name: string) {
185
+ return this.headers.first(name);
211
186
  }
212
187
 
213
- setHeader(
214
- /** @type {string} */name,
215
- /** @type {string} */ value
216
- ) {
217
- // name = name.toLocaleLowerCase();
218
- // for (const [key] of this.headers.keys()) {
219
- // if (key.toLocaleLowerCase() === name) {
220
- // this.headers.set(key, value);
221
- // return;
222
- // }
223
- // }
224
-
225
- // // change name...
226
- // switch(name.toLocaleLowerCase()) {
227
- // case "content-type":
228
- // name = "Content-Type";
229
- // break;
230
- // case "content-transfer-encoding":
231
- // name = "Content-Transfer-Encoding";
232
- // break;
233
- // case "content-disposition":
234
- // name = "Content-Disposition";
235
- // break;
236
- // }
237
-
188
+ setHeader(name: string, value: any): void {
238
189
  this.headers.set(name, value);
239
190
  }
240
191
 
241
- async asFile() {
242
- const text = this.encoded.split("\n").map((x) => x.trim()).join("");
192
+ async asFile(): Promise<AttachmentFile> {
193
+ const text = this.encoded!.split("\n").map((x) => x.trim()).join("");
243
194
  const url = `data:${this.contentType.type};base64,${text}`;
244
195
  const blob = await fetch(url);
245
196
  const af = new AttachmentFile(
246
197
  [await blob.blob()],
247
- this.contentDisposition.filename,
198
+ this.contentDisposition!.filename!,
248
199
  {
249
200
  type: this.contentType.type,
250
- contentId: this.header("Content-Id"),
251
- disposition: this.contentDisposition.type
201
+ contentId: this.firstHeaderString("Content-Id"),
202
+ disposition: this.contentDisposition!.type as any
252
203
  });
253
204
  af.node = this;
254
205
  return af;
255
206
  }
256
207
 
257
- async attachments(
258
- /** @type {AttachmentFile[]} */ files = []) {
259
- for (const iterator of this.children) {
208
+ async attachments(files: AttachmentFile[] = []): Promise<AttachmentFile[]> {
209
+ for (const iterator of this.children || []) {
260
210
  if (iterator.children) {
261
211
  await iterator.attachments(files);
262
212
  continue;
@@ -268,11 +218,7 @@ export class MimeNode {
268
218
  return files;
269
219
  }
270
220
 
271
- async parse(
272
- /** @type {LineStream} */ lines,
273
- last = ""
274
- ) {
275
-
221
+ async parse(lines: LineStream, last = ""): Promise<boolean> {
276
222
  await this.parseHeaders(lines);
277
223
 
278
224
  const end = last + "--";
@@ -319,15 +265,12 @@ export class MimeNode {
319
265
  this.children.push(child);
320
266
 
321
267
  if (isLast) {
322
- return;
268
+ return true;
323
269
  }
324
270
  }
325
271
  }
326
272
 
327
- async parseHeaders(
328
- /** @type {LineStream} */ lines
329
- ) {
330
-
273
+ async parseHeaders(lines: LineStream): Promise<void> {
331
274
  let headerName = "";
332
275
  let headerValue = "";
333
276
 
@@ -353,21 +296,9 @@ export class MimeNode {
353
296
  } else {
354
297
  return;
355
298
  }
356
-
357
- const ct = this.header("Content-Type");
358
- this.contentType.parse(ct);
359
- this.setHeader("Content-Type", ct);
360
-
361
- const cd = this.header("Content-Disposition");
362
- if (cd) {
363
- this.contentDisposition ??= new HeaderContentDisposition();
364
- this.contentDisposition.parse(cd);
365
- this.setHeader("Content-Disposition", cd);
366
- }
367
299
  }
368
300
 
369
- async save(/** @type {TextWriter} */ writer) {
370
-
301
+ async save(writer: TextWriter): Promise<void> {
371
302
  if (this.textContent) {
372
303
  this.contentType.charset = "UTF-8";
373
304
  }
@@ -376,26 +307,14 @@ export class MimeNode {
376
307
  this.contentType.boundary ||= `${Date.now()}-${Date.now()}-${Date.now()}`;
377
308
  }
378
309
 
379
- for (const [key, element] of this.headers.entries()) {
380
- switch(key) {
381
- case "content-disposition":
382
- writer.writeLine(`Content-Disposition: ${this.contentDisposition}`);
383
- continue;
384
- case "content-type":
385
- writer.writeLine(`Content-Type:${this.contentType.toString()}`);
386
- continue;
387
- case "subject":
388
- writer.writeLine(`${key}: ${wordEncoding.encode(element, true)}`);
389
- continue;
390
- }
391
- writer.writeLine(`${key}: ${element}`);
310
+ for (const h of this.headers.entries()) {
311
+ writer.writeLineMax80Chars(`${h.key}: ${wordEncoding.encode(h.value, true)}`);
392
312
  }
393
313
 
394
314
  writer.writeLine("");
395
315
 
396
316
  // check if we have any children...
397
317
  if (this.children?.length) {
398
-
399
318
  const boundary = `--${this.contentType.boundary}`;
400
319
 
401
320
  for (const iterator of this.children) {
@@ -404,8 +323,6 @@ export class MimeNode {
404
323
  }
405
324
 
406
325
  writer.writeLine(boundary + "--");
407
-
408
-
409
326
  return;
410
327
  }
411
328
 
@@ -416,7 +333,7 @@ export class MimeNode {
416
333
  let start = 0;
417
334
  const max = 80;
418
335
  for (;;) {
419
- if ( start + max > base64.length) {
336
+ if (start + max > base64.length) {
420
337
  writer.writeLine(base64.substring(start));
421
338
  break;
422
339
  }
@@ -429,23 +346,20 @@ export class MimeNode {
429
346
  let text = this.text;
430
347
  switch(this.contentTransferEncoding) {
431
348
  case "quoted-printable":
432
- text = quotedPrintable.encode( RawBuffer.encode(text));
349
+ text = quotedPrintable.encode(RawBuffer.encode(text));
433
350
  writer.writeLine(text);
434
351
  break;
435
352
  case "base64":
436
- text = btoa( RawBuffer.encode(text, this.contentType.charset));
437
- writer.writeLine(text);
353
+ text = btoa(RawBuffer.encode(text, this.contentType.charset));
354
+ writer.writeLineMax80Chars(text);
438
355
  break;
439
356
  default:
440
- writer.writeLine(text);
357
+ writer.writeLineMax80Chars(text);
441
358
  break;
442
359
  }
443
- // writer.writeLine("");
444
- return;
445
360
  }
446
361
 
447
- /** @returns {IterableIterator<MimeNode>} */
448
- *enumerate() {
362
+ *enumerate(): IterableIterator<MimeNode> {
449
363
  yield this;
450
364
  if (!this.children) {
451
365
  return;
@@ -454,4 +368,23 @@ export class MimeNode {
454
368
  yield* iterator.enumerate();
455
369
  }
456
370
  }
371
+
372
+ getFirstChild(contentType: string, create = false): MimeNode | undefined {
373
+ contentType = contentType.toLocaleLowerCase();
374
+ // const child = QueryIterator.first(this.descendent, (x) => x.contentType.type === contentType);
375
+ // The QueryIterator.first is not available, so we'll implement it manually:
376
+ let child: MimeNode | undefined;
377
+ for (const node of this.descendent) {
378
+ if (node.contentType.type === contentType) {
379
+ child = node;
380
+ break;
381
+ }
382
+ }
383
+
384
+ if (!child && create) {
385
+ child = new MimeNode(contentType);
386
+ (this.children ??= []).push(child);
387
+ }
388
+ return child;
389
+ }
457
390
  }
@@ -0,0 +1,42 @@
1
+ export default class RegexGenerator{
2
+
3
+ constructor(public readonly regex: RegExp) {
4
+
5
+ }
6
+
7
+ *groups(text: string) {
8
+ if (!text) {
9
+ return;
10
+ }
11
+ const { regex } = this;
12
+ regex.lastIndex = 0;
13
+ let m;
14
+ while((m = regex.exec(text)) !== null) {
15
+ if (m.index === regex.lastIndex) {
16
+ regex.lastIndex++;
17
+ }
18
+ if (m?.length) {
19
+ yield m as RegExpExecArray;
20
+ }
21
+ }
22
+ }
23
+
24
+ *all(text: string) {
25
+ if (!text) {
26
+ return;
27
+ }
28
+ const { regex } = this;
29
+ regex.lastIndex = 0;
30
+ let m;
31
+ while((m = regex.exec(text)) !== null) {
32
+ if (m.index === regex.lastIndex) {
33
+ regex.lastIndex++;
34
+ }
35
+ if (m?.length) {
36
+ yield { matched: m as RegExpExecArray };
37
+ continue;
38
+ }
39
+ }
40
+ }
41
+
42
+ };
@@ -1,6 +1,4 @@
1
- const toBuffer = (
2
- /** @type {string} */ text
3
- ) => {
1
+ const toBuffer = (text: string): ArrayBuffer => {
4
2
  const bytes = new Uint8Array(text.length);
5
3
  for (let index = 0; index < text.length; index++) {
6
4
  bytes[index] = text.charCodeAt(index);
@@ -9,10 +7,10 @@ const toBuffer = (
9
7
  };
10
8
 
11
9
  export const RawBuffer = {
12
- decode: (
13
- /** @type {string} */ bytesAsString,
14
- /** @type {string} */ encoding = "utf-8"
15
- ) => {
10
+ decode(
11
+ bytesAsString: string,
12
+ encoding: string = "utf-8"
13
+ ): string {
16
14
  if (!encoding) {
17
15
  return bytesAsString;
18
16
  }
@@ -20,16 +18,16 @@ export const RawBuffer = {
20
18
  return te.decode(toBuffer(bytesAsString));
21
19
  },
22
20
 
23
- encode: (
24
- /** @type {string} */ text,
25
- /** @type {string} */ encoding = "utf-8"
26
- ) => {
27
- if (!(/utf\-?8/i.test(encoding))) {
21
+ encode(
22
+ text: string,
23
+ encoding: string = "utf-8"
24
+ ): string {
25
+ if (!/utf\-?8/i.test(encoding)) {
28
26
  throw new Error(`Encoding ${encoding} not supported`);
29
27
  }
30
28
  const te = new TextEncoder();
31
29
  const array = te.encode(text);
32
- const a = [];
30
+ const a: string[] = [];
33
31
  for (const iterator of array) {
34
32
  a.push(String.fromCharCode(iterator));
35
33
  }
@@ -37,16 +35,16 @@ export const RawBuffer = {
37
35
  },
38
36
 
39
37
  toBase64Async(
40
- /** @type {Blob} */ blob,
41
- asDataUrl = false
42
- ) {
38
+ blob: Blob,
39
+ asDataUrl: boolean = false
40
+ ): Promise<string> {
43
41
  return new Promise<string>((resolve, reject) => {
44
42
  const reader = new FileReader();
45
43
  reader.onerror = () => {
46
44
  reject(reader.error);
47
45
  };
48
46
  reader.onload = () => {
49
- const /** @type {string} */ text = reader.result;
47
+ const text: string = reader.result as string;
50
48
  if (asDataUrl) {
51
49
  resolve(text);
52
50
  return;
@@ -1,26 +1,26 @@
1
1
  /**
2
- *
3
- * @param {string} base64Data
4
- * @param {string} contentType
5
- * @returns
2
+ * Converts a base64 string to a Blob
3
+ * @param {string} base64Data - The base64 encoded data
4
+ * @param {string} contentType - The content type of the blob
5
+ * @returns {Blob} - The resulting Blob object
6
6
  */
7
- export function base64toBlob(base64Data, contentType) {
7
+ export function base64toBlob(base64Data: string, contentType: string): Blob {
8
8
  contentType = contentType || '';
9
9
  const sliceSize = 1024;
10
10
  const byteCharacters = atob(base64Data);
11
11
  const bytesLength = byteCharacters.length;
12
12
  const slicesCount = Math.ceil(bytesLength / sliceSize);
13
- const byteArrays = new Array(slicesCount);
13
+ const byteArrays: Uint8Array[] = new Array(slicesCount);
14
14
 
15
15
  for (let sliceIndex = 0; sliceIndex < slicesCount; ++sliceIndex) {
16
16
  const begin = sliceIndex * sliceSize;
17
17
  const end = Math.min(begin + sliceSize, bytesLength);
18
18
 
19
- const bytes = new Array(end - begin);
19
+ const bytes: number[] = new Array(end - begin);
20
20
  for (let offset = begin, i = 0; offset < end; ++i, ++offset) {
21
21
  bytes[i] = byteCharacters[offset].charCodeAt(0);
22
22
  }
23
23
  byteArrays[sliceIndex] = new Uint8Array(bytes);
24
24
  }
25
- return new Blob(byteArrays, { type: contentType });
25
+ return new Blob(byteArrays as any, { type: contentType });
26
26
  }
@@ -1,8 +1,8 @@
1
1
  // Original Source Code: https://github.com/mathiasbynens/quoted-printable/blob/master/quoted-printable.js
2
2
 
3
-
4
3
  const stringFromCharCode = String.fromCharCode;
5
- const decode = function(input) {
4
+
5
+ const decode = function(input: string): string {
6
6
  return input
7
7
  // https://tools.ietf.org/html/rfc2045#section-6.7, rule 3:
8
8
  // “Therefore, when decoding a `Quoted-Printable` body, any trailing white
@@ -17,26 +17,23 @@ const decode = function(input) {
17
17
  // combination of two hexidecimal digits. For optimal compatibility,
18
18
  // lowercase hexadecimal digits are supported as well. See
19
19
  // https://tools.ietf.org/html/rfc2045#section-6.7, note 1.
20
- .replace(/=([a-fA-F0-9]{2})/g, function($0, $1) {
20
+ .replace(/=([a-fA-F0-9]{2})/g, function($0: string, $1: string): string {
21
21
  const codePoint = parseInt($1, 16);
22
22
  return stringFromCharCode(codePoint);
23
23
  });
24
24
  };
25
25
 
26
- const handleTrailingCharacters =
27
- function(
28
- /** @type {string} */
29
- text) {
26
+ const handleTrailingCharacters = function(text: string): string {
30
27
  return text
31
28
  .replace(/\x20$/, '=20') // Handle trailing space.
32
29
  .replace(/\t$/, '=09'); // Handle trailing tab.
33
30
  };
34
31
 
35
32
  const regexUnsafeSymbols = /[\0-\x08\n-\x1F=\x7F-\uFFFF]|[\uD800-\uDBFF][\uDC00-\uDFFF]/g;
36
- const encode = function(text) {
37
33
 
34
+ const encode = function(text: string): string {
38
35
  // Encode symbols that are definitely unsafe (i.e. unsafe in any context).
39
- const encoded = text.replace(regexUnsafeSymbols, function(symbol) {
36
+ const encoded = text.replace(regexUnsafeSymbols, function(symbol: string): string {
40
37
  if (symbol > '\xFF') {
41
38
  throw RangeError(
42
39
  '`quotedPrintable.encode()` expects extended ASCII input only. ' +
@@ -55,8 +52,9 @@ const encode = function(text) {
55
52
  const lines = encoded.split(/\r\n?|\n/g);
56
53
  let lineIndex = -1;
57
54
  const lineCount = lines.length;
58
- const result = [];
59
- let buffer;
55
+ const result: string[] = [];
56
+ let buffer: string;
57
+
60
58
  while (++lineIndex < lineCount) {
61
59
  const line = lines[lineIndex];
62
60
  // Leave room for the trailing `=` for soft line breaks.
@@ -5,20 +5,20 @@ const isEncodedRegEx = /\=\?([^\?\s]+)\?([^\?\s]{1})\?([^\s\?]+)\?\=\s*/gm;
5
5
  const hexToUnicode = /(\=([0-9a-f]{2}))|(\_)/gmi;
6
6
 
7
7
  const decode = (
8
- /** @type {string} */ text
9
- ) => {
10
- return text.replace(isEncodedRegEx, (matched, encoding, format, /** @type {string} */ buffer) => {
8
+ text: string
9
+ ): string => {
10
+ return text.replace(isEncodedRegEx, (matched: string, encoding: string, format: string, buffer: string): string => {
11
11
  if (/b/i.test(format)) {
12
12
  return RawBuffer.decode(atob(buffer), encoding);
13
13
  }
14
14
  if (/q/i.test(format)) {
15
- const replaced = buffer.replace(hexToUnicode, (m, group, /** @type {string} */ code, ) => {
15
+ const replaced = buffer.replace(hexToUnicode, (m: string, group: string, code: string): string => {
16
16
  if (m === "_") {
17
17
  return " ";
18
18
  }
19
19
  return String.fromCharCode(parseInt(code, 16));
20
20
  });
21
- return RawBuffer.decode( replaced, encoding);
21
+ return RawBuffer.decode(replaced, encoding);
22
22
  }
23
23
  return matched;
24
24
  });
@@ -29,7 +29,7 @@ const isSimpleText = /[0-9a-zA-Z\x20]/;
29
29
  export const wordEncoding = {
30
30
  decode,
31
31
 
32
- encode: (/** @type {string} */ word, ifNeeded = false) => {
32
+ encode: (word: string, ifNeeded: boolean = false): string => {
33
33
 
34
34
  if(ifNeeded) {
35
35
  if(isSimpleText.test(word)) {
@@ -1,14 +1,15 @@
1
1
  import { tokenize, tokenizeMax } from "./tokenizer.js";
2
2
 
3
-
4
3
  export const parsePairs = (
5
- /** @type {string} */ text,
6
- /** @type {string} */ emptyName) => {
4
+ text: string,
5
+ emptyName?: string
6
+ ): Record<string, string> & { toString(): string } => {
7
7
  const pairs = {
8
8
  toString() {
9
9
  return text;
10
10
  }
11
- };
11
+ } as Record<string, string> & { toString(): string };
12
+
12
13
  for (const iterator of tokenize(text, ";")) {
13
14
  const trimmed = iterator.trim();
14
15
  if (!trimmed) {