@social-mail/shared 1.0.28 → 1.1.3

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 (88) hide show
  1. package/.gitlab-ci.yml +3 -3
  2. package/dist/.tsbuildinfo +1 -0
  3. package/dist/QueryIterator.d.ts +1 -9
  4. package/dist/QueryIterator.d.ts.map +1 -1
  5. package/dist/QueryIterator.js +3 -14
  6. package/dist/QueryIterator.js.map +1 -1
  7. package/dist/ical-parser/Calender.d.ts +6 -4
  8. package/dist/ical-parser/Calender.d.ts.map +1 -1
  9. package/dist/ical-parser/Calender.js +42 -90
  10. package/dist/ical-parser/Calender.js.map +1 -1
  11. package/dist/ical-parser/ics.d.ts +4 -0
  12. package/dist/ical-parser/ics.d.ts.map +1 -0
  13. package/dist/ical-parser/ics.js +6 -0
  14. package/dist/ical-parser/ics.js.map +1 -0
  15. package/dist/ical-parser/parseDate.js +1 -5
  16. package/dist/ical-parser/parseDate.js.map +1 -1
  17. package/dist/mime-parser/AttachmentFile.d.ts +5 -11
  18. package/dist/mime-parser/AttachmentFile.d.ts.map +1 -1
  19. package/dist/mime-parser/AttachmentFile.js +3 -8
  20. package/dist/mime-parser/AttachmentFile.js.map +1 -1
  21. package/dist/mime-parser/HeaderContentDisposition.d.ts +5 -5
  22. package/dist/mime-parser/HeaderContentDisposition.d.ts.map +1 -1
  23. package/dist/mime-parser/HeaderContentDisposition.js +2 -5
  24. package/dist/mime-parser/HeaderContentDisposition.js.map +1 -1
  25. package/dist/mime-parser/HeaderContentType.d.ts +5 -5
  26. package/dist/mime-parser/HeaderContentType.d.ts.map +1 -1
  27. package/dist/mime-parser/HeaderContentType.js +2 -5
  28. package/dist/mime-parser/HeaderContentType.js.map +1 -1
  29. package/dist/mime-parser/MimeMessage.d.ts +11 -11
  30. package/dist/mime-parser/MimeMessage.d.ts.map +1 -1
  31. package/dist/mime-parser/MimeMessage.js +46 -72
  32. package/dist/mime-parser/MimeMessage.js.map +1 -1
  33. package/dist/mime-parser/MimeNode.d.ts +28 -38
  34. package/dist/mime-parser/MimeNode.d.ts.map +1 -1
  35. package/dist/mime-parser/MimeNode.js +171 -295
  36. package/dist/mime-parser/MimeNode.js.map +1 -1
  37. package/dist/mime-parser/encoder/RawBuffer.d.ts +5 -5
  38. package/dist/mime-parser/encoder/RawBuffer.d.ts.map +1 -1
  39. package/dist/mime-parser/encoder/RawBuffer.js +7 -13
  40. package/dist/mime-parser/encoder/RawBuffer.js.map +1 -1
  41. package/dist/mime-parser/encoder/base64-to-blob.d.ts +1 -7
  42. package/dist/mime-parser/encoder/base64-to-blob.d.ts.map +1 -1
  43. package/dist/mime-parser/encoder/base64-to-blob.js +0 -6
  44. package/dist/mime-parser/encoder/base64-to-blob.js.map +1 -1
  45. package/dist/mime-parser/encoder/quoted-printable.d.ts +5 -8
  46. package/dist/mime-parser/encoder/quoted-printable.d.ts.map +1 -1
  47. package/dist/mime-parser/encoder/quoted-printable.js +3 -34
  48. package/dist/mime-parser/encoder/quoted-printable.js.map +1 -1
  49. package/dist/mime-parser/encoder/word-encoding.d.ts +4 -6
  50. package/dist/mime-parser/encoder/word-encoding.d.ts.map +1 -1
  51. package/dist/mime-parser/encoder/word-encoding.js +4 -5
  52. package/dist/mime-parser/encoder/word-encoding.js.map +1 -1
  53. package/dist/mime-parser/parsePairs.d.ts +1 -1
  54. package/dist/mime-parser/parsePairs.d.ts.map +1 -1
  55. package/dist/mime-parser/parsePairs.js +3 -7
  56. package/dist/mime-parser/parsePairs.js.map +1 -1
  57. package/dist/mime-parser/stream/LineStream.d.ts +10 -16
  58. package/dist/mime-parser/stream/LineStream.d.ts.map +1 -1
  59. package/dist/mime-parser/stream/LineStream.js +59 -94
  60. package/dist/mime-parser/stream/LineStream.js.map +1 -1
  61. package/dist/mime-parser/stream/TextWriter.d.ts +4 -3
  62. package/dist/mime-parser/stream/TextWriter.d.ts.map +1 -1
  63. package/dist/mime-parser/stream/TextWriter.js +2 -3
  64. package/dist/mime-parser/stream/TextWriter.js.map +1 -1
  65. package/dist/mime-parser/tokenizer.d.ts +3 -3
  66. package/dist/mime-parser/tokenizer.d.ts.map +1 -1
  67. package/dist/mime-parser/tokenizer.js +10 -17
  68. package/dist/mime-parser/tokenizer.js.map +1 -1
  69. package/package.json +3 -3
  70. package/src/{QueryIterator.js → QueryIterator.ts} +11 -12
  71. package/src/ical-parser/Calender.ts +12 -3
  72. package/src/ical-parser/ics.ts +7 -0
  73. package/src/mime-parser/AttachmentFile.ts +24 -0
  74. package/src/mime-parser/{HeaderContentDisposition.js → HeaderContentDisposition.ts} +7 -17
  75. package/src/mime-parser/{HeaderContentType.js → HeaderContentType.ts} +7 -18
  76. package/src/mime-parser/{MimeMessage.js → MimeMessage.ts} +25 -35
  77. package/src/mime-parser/{MimeNode.js → MimeNode.ts} +75 -133
  78. package/src/mime-parser/encoder/{RawBuffer.js → RawBuffer.ts} +15 -17
  79. package/src/mime-parser/encoder/{base64-to-blob.js → base64-to-blob.ts} +8 -8
  80. package/src/mime-parser/encoder/{quoted-printable.js → quoted-printable.ts} +9 -11
  81. package/src/mime-parser/encoder/{word-encoding.js → word-encoding.ts} +6 -6
  82. package/src/mime-parser/{parsePairs.js → parsePairs.ts} +5 -4
  83. package/src/mime-parser/stream/{LineStream.js → LineStream.ts} +12 -19
  84. package/src/mime-parser/stream/{TextWriter.js → TextWriter.ts} +5 -10
  85. package/src/mime-parser/{tokenizer.js → tokenizer.ts} +24 -21
  86. package/tsconfig.json +30 -9
  87. package/dist/tsconfig.tsbuildinfo +0 -1
  88. package/src/mime-parser/AttachmentFile.js +0 -29
@@ -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";
@@ -10,31 +9,13 @@ import { wordEncoding } from "./encoder/word-encoding.js";
10
9
  import LineStream from "./stream/LineStream.js";
11
10
  import TextWriter from "./stream/TextWriter.js";
12
11
 
13
- // export interface IContentTypeObject {
14
- // type: string;
15
- // boundary?: string;
16
- // charset?: string
17
- // };
12
+ export class CIMap extends Map<string, any> {
13
+ private ci = new Map<string, string>();
18
14
 
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) {
15
+ set(key: string, value: any): this {
35
16
  if (typeof key === "string") {
36
17
  let ck = this.ci.get(key);
37
- if (ck === void 0) {
18
+ if (ck === undefined) {
38
19
  ck = key.toLocaleLowerCase();
39
20
  this.ci.set(ck, key);
40
21
  } else {
@@ -44,26 +25,29 @@ export class CIMap extends Map {
44
25
  return super.set(key, value);
45
26
  }
46
27
 
47
- get(key) {
28
+ get(key: string): any {
48
29
  if (typeof key === "string") {
49
30
  const ck = key.toLocaleLowerCase();
50
- key = this.ci.get(ck);
31
+ key = this.ci.get(ck) || key;
51
32
  }
52
33
  return super.get(key);
53
34
  }
54
-
55
35
  }
56
36
 
57
-
58
37
  export class MimeNode {
59
-
60
38
  static createMessage({
61
39
  html,
62
40
  subject,
63
41
  text = "",
64
42
  name = "",
65
43
  attachments = []
66
- }) {
44
+ }: {
45
+ html?: string;
46
+ subject: string;
47
+ text?: string;
48
+ name?: string;
49
+ attachments?: any[];
50
+ }): MimeNode {
67
51
  const root = new MimeNode("multipart/mixed");
68
52
  root.setHeader("Subject", subject);
69
53
  if (name) {
@@ -87,11 +71,12 @@ export class MimeNode {
87
71
  }
88
72
 
89
73
  static create(
90
- /** @type {string | File} */ text,
91
- /** @type {string} */ type,
92
- /** @type {string} */id) {
74
+ text: string | File,
75
+ type?: string,
76
+ id?: string
77
+ ): MimeNode {
93
78
  if (typeof text === "string") {
94
- const node = new MimeNode(type);
79
+ const node = new MimeNode(type || "");
95
80
  node.text = text;
96
81
  return node;
97
82
  }
@@ -106,23 +91,28 @@ export class MimeNode {
106
91
  return fileNode;
107
92
  }
108
93
 
109
- /** @type {string} */ encoded;
94
+ encoded?: string;
95
+ children?: MimeNode[];
96
+ contentType: HeaderContentType;
97
+ contentDisposition?: HeaderContentDisposition;
98
+ textContent?: string;
99
+ blobData?: Blob;
100
+ headers: CIMap;
110
101
 
111
- /** @type {MimeNode[]} */ children;
112
-
113
- /** @type {HeaderContentType} */ contentType;
114
-
115
- /** @type {HeaderContentDisposition} */ contentDisposition;
102
+ constructor(type?: string) {
103
+ this.headers = new CIMap();
104
+ this.contentType = new HeaderContentType(type);
105
+ this.headers.set("Content-Type", this.contentType);
106
+ }
116
107
 
117
- /** @returns {string} */
118
- get text() {
108
+ get text(): string {
119
109
  let tc = this.textContent;
120
110
  if (tc) {
121
111
  return tc;
122
112
  }
123
113
  let { encoded } = this;
124
114
  if (!encoded) {
125
- return;
115
+ return "";
126
116
  }
127
117
  // we need to convert byte array to utf8
128
118
  const cte = this.contentTransferEncoding?.toLowerCase();
@@ -145,118 +135,65 @@ export class MimeNode {
145
135
  return tc;
146
136
  }
147
137
 
148
- set text( /** @type {string} */ v) {
138
+ set text(v: string) {
149
139
  this.contentTransferEncoding = "quoted-printable";
150
140
  this.textContent = v;
151
141
  }
152
142
 
153
- /** @returns {Blob} */
154
- get blob() {
143
+ get blob(): Blob {
155
144
  // this will create blob..
156
145
  if (this.contentTransferEncoding?.toLocaleLowerCase() !== "base64") {
157
146
  throw new Error("Not supported");
158
147
  }
159
- return this.blobData ??= base64toBlob(this.encoded, this.contentType.type);
148
+ return this.blobData ??= base64toBlob(this.encoded!, this.contentType.type);
160
149
  }
161
150
 
162
- set blob( /** @type {Blob} */ v) {
151
+ set blob(v: Blob) {
163
152
  this.blobData = v;
164
153
  }
165
154
 
166
- /** @returns {string} */
167
- get contentTransferEncoding() {
155
+ get contentTransferEncoding(): string | undefined {
168
156
  return this.header("Content-Transfer-Encoding");
169
157
  }
170
158
 
171
- set contentTransferEncoding( /** @type {string} */ v) {
159
+ set contentTransferEncoding(v: string | undefined) {
172
160
  this.setHeader("Content-Transfer-Encoding", v);
173
161
  }
174
162
 
175
- /** @returns {string} */
176
- get boundary() {
163
+ get boundary(): string | undefined {
177
164
  return this.contentType.boundary;
178
165
  }
179
166
 
180
- /** @returns {IterableIterator<MimeNode>} */
181
- get descendent() {
167
+ get descendent(): IterableIterator<MimeNode> {
182
168
  return this.enumerate();
183
169
  }
184
170
 
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;
207
- }
208
-
209
- header(/** @type {string} */ name) {
171
+ header(name: string): any {
210
172
  return this.headers.get(name);
211
173
  }
212
174
 
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
-
175
+ setHeader(name: string, value: any): void {
238
176
  this.headers.set(name, value);
239
177
  }
240
178
 
241
- async asFile() {
242
- const text = this.encoded.split("\n").map((x) => x.trim()).join("");
179
+ async asFile(): Promise<AttachmentFile> {
180
+ const text = this.encoded!.split("\n").map((x) => x.trim()).join("");
243
181
  const url = `data:${this.contentType.type};base64,${text}`;
244
182
  const blob = await fetch(url);
245
183
  const af = new AttachmentFile(
246
184
  [await blob.blob()],
247
- this.contentDisposition.filename,
185
+ this.contentDisposition!.filename!,
248
186
  {
249
187
  type: this.contentType.type,
250
188
  contentId: this.header("Content-Id"),
251
- disposition: this.contentDisposition.type
189
+ disposition: this.contentDisposition!.type as any
252
190
  });
253
191
  af.node = this;
254
192
  return af;
255
193
  }
256
194
 
257
- async attachments(
258
- /** @type {AttachmentFile[]} */ files = []) {
259
- for (const iterator of this.children) {
195
+ async attachments(files: AttachmentFile[] = []): Promise<AttachmentFile[]> {
196
+ for (const iterator of this.children || []) {
260
197
  if (iterator.children) {
261
198
  await iterator.attachments(files);
262
199
  continue;
@@ -268,11 +205,7 @@ export class MimeNode {
268
205
  return files;
269
206
  }
270
207
 
271
- async parse(
272
- /** @type {LineStream} */ lines,
273
- last = ""
274
- ) {
275
-
208
+ async parse(lines: LineStream, last = ""): Promise<boolean> {
276
209
  await this.parseHeaders(lines);
277
210
 
278
211
  const end = last + "--";
@@ -319,15 +252,12 @@ export class MimeNode {
319
252
  this.children.push(child);
320
253
 
321
254
  if (isLast) {
322
- return;
255
+ return true;
323
256
  }
324
257
  }
325
258
  }
326
259
 
327
- async parseHeaders(
328
- /** @type {LineStream} */ lines
329
- ) {
330
-
260
+ async parseHeaders(lines: LineStream): Promise<void> {
331
261
  let headerName = "";
332
262
  let headerValue = "";
333
263
 
@@ -366,8 +296,7 @@ export class MimeNode {
366
296
  }
367
297
  }
368
298
 
369
- async save(/** @type {TextWriter} */ writer) {
370
-
299
+ async save(writer: TextWriter): Promise<void> {
371
300
  if (this.textContent) {
372
301
  this.contentType.charset = "UTF-8";
373
302
  }
@@ -395,7 +324,6 @@ export class MimeNode {
395
324
 
396
325
  // check if we have any children...
397
326
  if (this.children?.length) {
398
-
399
327
  const boundary = `--${this.contentType.boundary}`;
400
328
 
401
329
  for (const iterator of this.children) {
@@ -404,8 +332,6 @@ export class MimeNode {
404
332
  }
405
333
 
406
334
  writer.writeLine(boundary + "--");
407
-
408
-
409
335
  return;
410
336
  }
411
337
 
@@ -416,7 +342,7 @@ export class MimeNode {
416
342
  let start = 0;
417
343
  const max = 80;
418
344
  for (;;) {
419
- if ( start + max > base64.length) {
345
+ if (start + max > base64.length) {
420
346
  writer.writeLine(base64.substring(start));
421
347
  break;
422
348
  }
@@ -429,23 +355,20 @@ export class MimeNode {
429
355
  let text = this.text;
430
356
  switch(this.contentTransferEncoding) {
431
357
  case "quoted-printable":
432
- text = quotedPrintable.encode( RawBuffer.encode(text));
358
+ text = quotedPrintable.encode(RawBuffer.encode(text));
433
359
  writer.writeLine(text);
434
360
  break;
435
361
  case "base64":
436
- text = btoa( RawBuffer.encode(text, this.contentType.charset));
362
+ text = btoa(RawBuffer.encode(text, this.contentType.charset));
437
363
  writer.writeLine(text);
438
364
  break;
439
365
  default:
440
366
  writer.writeLine(text);
441
367
  break;
442
368
  }
443
- // writer.writeLine("");
444
- return;
445
369
  }
446
370
 
447
- /** @returns {IterableIterator<MimeNode>} */
448
- *enumerate() {
371
+ *enumerate(): IterableIterator<MimeNode> {
449
372
  yield this;
450
373
  if (!this.children) {
451
374
  return;
@@ -454,4 +377,23 @@ export class MimeNode {
454
377
  yield* iterator.enumerate();
455
378
  }
456
379
  }
380
+
381
+ getFirstChild(contentType: string, create = false): MimeNode | undefined {
382
+ contentType = contentType.toLocaleLowerCase();
383
+ // const child = QueryIterator.first(this.descendent, (x) => x.contentType.type === contentType);
384
+ // The QueryIterator.first is not available, so we'll implement it manually:
385
+ let child: MimeNode | undefined;
386
+ for (const node of this.descendent) {
387
+ if (node.contentType.type === contentType) {
388
+ child = node;
389
+ break;
390
+ }
391
+ }
392
+
393
+ if (!child && create) {
394
+ child = new MimeNode(contentType);
395
+ (this.children ??= []).push(child);
396
+ }
397
+ return child;
398
+ }
457
399
  }
@@ -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) {
@@ -1,13 +1,12 @@
1
1
  import { tokenize } from "../tokenizer.js";
2
2
 
3
3
  export default class LineStream {
4
-
5
- /** @type {AsyncGenerator<string, any, any>} */ g;
4
+ protected g?: AsyncGenerator<string, any, any>;
6
5
 
7
6
  /**
8
7
  * @returns {AsyncGenerator<string, any, any>}
9
8
  */
10
- async *read() {
9
+ async *read(): AsyncGenerator<string, any, any> {
11
10
  const g = this.g ??= this.lines();
12
11
  for(;;) {
13
12
  const { value , done } = await g.next();
@@ -21,8 +20,8 @@ export default class LineStream {
21
20
  /**
22
21
  * @returns {AsyncGenerator<string, any, any>}
23
22
  */
24
- async *readRFCHeaders() {
25
- let last;
23
+ async *readRFCHeaders(): AsyncGenerator<string, any, any> {
24
+ let last: string | undefined;
26
25
  const g = this.g ??= this.lines();
27
26
  for(;;) {
28
27
  const { value , done } = await g.next();
@@ -30,7 +29,7 @@ export default class LineStream {
30
29
  break;
31
30
  }
32
31
  if (/^\s+/i.test(value)) {
33
- last += value.trimStart();
32
+ last = last + value.trimStart();
34
33
  continue;
35
34
  }
36
35
  if (last) {
@@ -44,26 +43,22 @@ export default class LineStream {
44
43
  }
45
44
 
46
45
  /** @returns {AsyncGenerator<string, any,any>} */
47
- lines() {
46
+ protected lines(): AsyncGenerator<string, any, any> {
48
47
  throw new Error("Not Implemented");
49
48
  }
50
49
  }
51
50
 
52
51
  export class StringLineStream extends LineStream {
53
52
 
54
- /** @type {string} */ text;
55
-
56
53
  constructor(
57
- /** @type {string} */ text,
58
- /** @type {boolean} */ trimR
54
+ protected text: string,
55
+ protected trimR?: boolean
59
56
  ) {
60
57
  super();
61
- this.text = text;
62
- this.trimR = trimR;
63
58
  }
64
59
 
65
60
  /** @returns {AsyncGenerator<string, any, any>} */
66
- async *lines() {
61
+ async *lines(): AsyncGenerator<string, any, any> {
67
62
  if (this.trimR) {
68
63
  for (const iterator of tokenize(this.text, "\n")) {
69
64
  yield iterator.replace(/\r*$/, "");
@@ -77,17 +72,15 @@ export class StringLineStream extends LineStream {
77
72
  }
78
73
 
79
74
  export class ReadableLineStream extends LineStream {
75
+ protected readable: ReadableStream;
80
76
 
81
- /** @type {ReadableStream} */
82
- readable;
83
-
84
- constructor( /** @type {ReadableStream} */ readable) {
77
+ constructor(readable: ReadableStream) {
85
78
  super();
86
79
  this.readable = readable;
87
80
  }
88
81
 
89
82
  /** @returns {AsyncGenerator<string, any, any>} */
90
- async *lines() {
83
+ async *lines(): AsyncGenerator<string, any, any> {
91
84
  const utf8Decoder = new TextDecoder("utf-8");
92
85
  const reader = this.readable.getReader();
93
86
  let { value: chunk, done: readerDone } = await reader.read();