@postalsys/email-content 0.0.1
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/LICENSE +21 -0
- package/README.md +288 -0
- package/dist/.tsbuildinfo +1 -0
- package/dist/analyze.d.ts +91 -0
- package/dist/analyze.d.ts.map +1 -0
- package/dist/analyze.js +274 -0
- package/dist/analyze.js.map +1 -0
- package/dist/annotate/client.d.ts +64 -0
- package/dist/annotate/client.d.ts.map +1 -0
- package/dist/annotate/client.js +139 -0
- package/dist/annotate/client.js.map +1 -0
- package/dist/annotate/llm.d.ts +46 -0
- package/dist/annotate/llm.d.ts.map +1 -0
- package/dist/annotate/llm.js +107 -0
- package/dist/annotate/llm.js.map +1 -0
- package/dist/annotate/prompt.d.ts +38 -0
- package/dist/annotate/prompt.d.ts.map +1 -0
- package/dist/annotate/prompt.js +165 -0
- package/dist/annotate/prompt.js.map +1 -0
- package/dist/annotate/store.d.ts +43 -0
- package/dist/annotate/store.d.ts.map +1 -0
- package/dist/annotate/store.js +46 -0
- package/dist/annotate/store.js.map +1 -0
- package/dist/canonical/html.d.ts +33 -0
- package/dist/canonical/html.d.ts.map +1 -0
- package/dist/canonical/html.js +156 -0
- package/dist/canonical/html.js.map +1 -0
- package/dist/canonical/text.d.ts +75 -0
- package/dist/canonical/text.d.ts.map +1 -0
- package/dist/canonical/text.js +217 -0
- package/dist/canonical/text.js.map +1 -0
- package/dist/classify/confidence.d.ts +38 -0
- package/dist/classify/confidence.d.ts.map +1 -0
- package/dist/classify/confidence.js +59 -0
- package/dist/classify/confidence.js.map +1 -0
- package/dist/classify/reconcile.d.ts +52 -0
- package/dist/classify/reconcile.d.ts.map +1 -0
- package/dist/classify/reconcile.js +100 -0
- package/dist/classify/reconcile.js.map +1 -0
- package/dist/classify/rules.d.ts +51 -0
- package/dist/classify/rules.d.ts.map +1 -0
- package/dist/classify/rules.js +648 -0
- package/dist/classify/rules.js.map +1 -0
- package/dist/cli/annotate.d.ts +23 -0
- package/dist/cli/annotate.d.ts.map +1 -0
- package/dist/cli/annotate.js +328 -0
- package/dist/cli/annotate.js.map +1 -0
- package/dist/cli/args.d.ts +17 -0
- package/dist/cli/args.d.ts.map +1 -0
- package/dist/cli/args.js +72 -0
- package/dist/cli/args.js.map +1 -0
- package/dist/cli/benchmark.d.ts +13 -0
- package/dist/cli/benchmark.d.ts.map +1 -0
- package/dist/cli/benchmark.js +172 -0
- package/dist/cli/benchmark.js.map +1 -0
- package/dist/cli/corpus.d.ts +9 -0
- package/dist/cli/corpus.d.ts.map +1 -0
- package/dist/cli/corpus.js +152 -0
- package/dist/cli/corpus.js.map +1 -0
- package/dist/cli/disagreements.d.ts +14 -0
- package/dist/cli/disagreements.d.ts.map +1 -0
- package/dist/cli/disagreements.js +133 -0
- package/dist/cli/disagreements.js.map +1 -0
- package/dist/cli/evaluate.d.ts +15 -0
- package/dist/cli/evaluate.d.ts.map +1 -0
- package/dist/cli/evaluate.js +215 -0
- package/dist/cli/evaluate.js.map +1 -0
- package/dist/cli/extract.d.ts +10 -0
- package/dist/cli/extract.d.ts.map +1 -0
- package/dist/cli/extract.js +139 -0
- package/dist/cli/extract.js.map +1 -0
- package/dist/cli/main.d.ts +9 -0
- package/dist/cli/main.d.ts.map +1 -0
- package/dist/cli/main.js +147 -0
- package/dist/cli/main.js.map +1 -0
- package/dist/corpus/analyze.d.ts +66 -0
- package/dist/corpus/analyze.d.ts.map +1 -0
- package/dist/corpus/analyze.js +214 -0
- package/dist/corpus/analyze.js.map +1 -0
- package/dist/corpus/migrations/index.d.ts +14 -0
- package/dist/corpus/migrations/index.d.ts.map +1 -0
- package/dist/corpus/migrations/index.js +158 -0
- package/dist/corpus/migrations/index.js.map +1 -0
- package/dist/corpus/sample.d.ts +66 -0
- package/dist/corpus/sample.d.ts.map +1 -0
- package/dist/corpus/sample.js +98 -0
- package/dist/corpus/sample.js.map +1 -0
- package/dist/corpus/scanner.d.ts +79 -0
- package/dist/corpus/scanner.d.ts.map +1 -0
- package/dist/corpus/scanner.js +256 -0
- package/dist/corpus/scanner.js.map +1 -0
- package/dist/corpus/stats.d.ts +76 -0
- package/dist/corpus/stats.d.ts.map +1 -0
- package/dist/corpus/stats.js +240 -0
- package/dist/corpus/stats.js.map +1 -0
- package/dist/corpus/store.d.ts +67 -0
- package/dist/corpus/store.d.ts.map +1 -0
- package/dist/corpus/store.js +196 -0
- package/dist/corpus/store.js.map +1 -0
- package/dist/corpus/thread-index.d.ts +31 -0
- package/dist/corpus/thread-index.d.ts.map +1 -0
- package/dist/corpus/thread-index.js +182 -0
- package/dist/corpus/thread-index.js.map +1 -0
- package/dist/corpus/worker.d.ts +21 -0
- package/dist/corpus/worker.d.ts.map +1 -0
- package/dist/corpus/worker.js +74 -0
- package/dist/corpus/worker.js.map +1 -0
- package/dist/detect/client.d.ts +28 -0
- package/dist/detect/client.d.ts.map +1 -0
- package/dist/detect/client.js +121 -0
- package/dist/detect/client.js.map +1 -0
- package/dist/detect/disclaimer.d.ts +12 -0
- package/dist/detect/disclaimer.d.ts.map +1 -0
- package/dist/detect/disclaimer.js +28 -0
- package/dist/detect/disclaimer.js.map +1 -0
- package/dist/detect/forward-header.d.ts +10 -0
- package/dist/detect/forward-header.d.ts.map +1 -0
- package/dist/detect/forward-header.js +35 -0
- package/dist/detect/forward-header.js.map +1 -0
- package/dist/detect/patterns/disclaimers.json +113 -0
- package/dist/detect/patterns/forward-headers.json +40 -0
- package/dist/detect/patterns/html-clients.json +157 -0
- package/dist/detect/patterns/quoted-headers.json +41 -0
- package/dist/detect/patterns/reply-headers.json +139 -0
- package/dist/detect/patterns/signatures.json +58 -0
- package/dist/detect/patterns.d.ts +43 -0
- package/dist/detect/patterns.d.ts.map +1 -0
- package/dist/detect/patterns.js +125 -0
- package/dist/detect/patterns.js.map +1 -0
- package/dist/detect/reply-header.d.ts +44 -0
- package/dist/detect/reply-header.d.ts.map +1 -0
- package/dist/detect/reply-header.js +134 -0
- package/dist/detect/reply-header.js.map +1 -0
- package/dist/detect/signature.d.ts +28 -0
- package/dist/detect/signature.d.ts.map +1 -0
- package/dist/detect/signature.js +77 -0
- package/dist/detect/signature.js.map +1 -0
- package/dist/detect/traffic.d.ts +26 -0
- package/dist/detect/traffic.d.ts.map +1 -0
- package/dist/detect/traffic.js +98 -0
- package/dist/detect/traffic.js.map +1 -0
- package/dist/eval/metrics.d.ts +87 -0
- package/dist/eval/metrics.d.ts.map +1 -0
- package/dist/eval/metrics.js +185 -0
- package/dist/eval/metrics.js.map +1 -0
- package/dist/index.d.ts +54 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +163 -0
- package/dist/index.js.map +1 -0
- package/dist/match/history.d.ts +62 -0
- package/dist/match/history.d.ts.map +1 -0
- package/dist/match/history.js +128 -0
- package/dist/match/history.js.map +1 -0
- package/dist/match/normalize.d.ts +33 -0
- package/dist/match/normalize.d.ts.map +1 -0
- package/dist/match/normalize.js +63 -0
- package/dist/match/normalize.js.map +1 -0
- package/dist/match/shingle.d.ts +44 -0
- package/dist/match/shingle.d.ts.map +1 -0
- package/dist/match/shingle.js +78 -0
- package/dist/match/shingle.js.map +1 -0
- package/dist/mime/charset.d.ts +33 -0
- package/dist/mime/charset.d.ts.map +1 -0
- package/dist/mime/charset.js +118 -0
- package/dist/mime/charset.js.map +1 -0
- package/dist/mime/headers.d.ts +32 -0
- package/dist/mime/headers.d.ts.map +1 -0
- package/dist/mime/headers.js +127 -0
- package/dist/mime/headers.js.map +1 -0
- package/dist/mime/model.d.ts +111 -0
- package/dist/mime/model.d.ts.map +1 -0
- package/dist/mime/model.js +17 -0
- package/dist/mime/model.js.map +1 -0
- package/dist/mime/parse.d.ts +27 -0
- package/dist/mime/parse.d.ts.map +1 -0
- package/dist/mime/parse.js +343 -0
- package/dist/mime/parse.js.map +1 -0
- package/dist/segment/features.d.ts +29 -0
- package/dist/segment/features.d.ts.map +1 -0
- package/dist/segment/features.js +102 -0
- package/dist/segment/features.js.map +1 -0
- package/dist/segment/html-blocks.d.ts +28 -0
- package/dist/segment/html-blocks.d.ts.map +1 -0
- package/dist/segment/html-blocks.js +596 -0
- package/dist/segment/html-blocks.js.map +1 -0
- package/dist/segment/text-blocks.d.ts +30 -0
- package/dist/segment/text-blocks.d.ts.map +1 -0
- package/dist/segment/text-blocks.js +204 -0
- package/dist/segment/text-blocks.js.map +1 -0
- package/dist/segment/types.d.ts +88 -0
- package/dist/segment/types.d.ts.map +1 -0
- package/dist/segment/types.js +11 -0
- package/dist/segment/types.js.map +1 -0
- package/dist/types.d.ts +85 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +17 -0
- package/dist/types.js.map +1 -0
- package/dist/util/hash.d.ts +49 -0
- package/dist/util/hash.d.ts.map +1 -0
- package/dist/util/hash.js +0 -0
- package/dist/util/hash.js.map +1 -0
- package/dist/util/lang.d.ts +25 -0
- package/dist/util/lang.d.ts.map +1 -0
- package/dist/util/lang.js +135 -0
- package/dist/util/lang.js.map +1 -0
- package/dist/util/worker-pool.d.ts +51 -0
- package/dist/util/worker-pool.d.ts.map +1 -0
- package/dist/util/worker-pool.js +155 -0
- package/dist/util/worker-pool.js.map +1 -0
- package/package.json +74 -0
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
{
|
|
2
|
+
"description": "Machine appended boilerplate, per the DISCLAIMER convention in docs/annotation-guide.md: text attached by a system, gateway or template independently of what the sender wrote. Matching is on the block as a whole. Deliberately generic: patterns target the shapes that recur across senders, not any one vendor's template, because fitting a single sender's footer would not transfer.",
|
|
3
|
+
"phrases": [
|
|
4
|
+
{
|
|
5
|
+
"id": "confidentiality_en",
|
|
6
|
+
"strength": 0.9,
|
|
7
|
+
"flags": "i",
|
|
8
|
+
"pattern": "(this (e-?mail|message)[^.]{0,80}(is )?(strictly )?confidential|confidential and (may be )?(legally )?privileged|intended (solely |only )?for the (named |intended )?(addressee|recipient))"
|
|
9
|
+
},
|
|
10
|
+
{
|
|
11
|
+
"id": "unintended_recipient_en",
|
|
12
|
+
"strength": 0.9,
|
|
13
|
+
"flags": "i",
|
|
14
|
+
"pattern": "(if you (have received|are not) .{0,80}(in error|the intended recipient)|please (notify the sender|delete) .{0,60}(immediately|and delete))"
|
|
15
|
+
},
|
|
16
|
+
{
|
|
17
|
+
"id": "no_liability_en",
|
|
18
|
+
"strength": 0.7,
|
|
19
|
+
"flags": "i",
|
|
20
|
+
"pattern": "(accepts? no (liability|responsibility)|any views or opinions (presented|expressed) .{0,60}are (solely )?those of the (author|sender))"
|
|
21
|
+
},
|
|
22
|
+
{
|
|
23
|
+
"id": "virus_scan_en",
|
|
24
|
+
"strength": 0.7,
|
|
25
|
+
"flags": "i",
|
|
26
|
+
"pattern": "(this (e-?mail|message) has been (scanned|checked) for viruses|virus-free|free from (any )?virus)"
|
|
27
|
+
},
|
|
28
|
+
{
|
|
29
|
+
"id": "confidentiality_de",
|
|
30
|
+
"strength": 0.9,
|
|
31
|
+
"flags": "i",
|
|
32
|
+
"pattern": "(vertrauliche Informationen|Diese E-?Mail (ist|enthält) .{0,60}vertraulich|Sollten Sie nicht der richtige Adressat sein)"
|
|
33
|
+
},
|
|
34
|
+
{
|
|
35
|
+
"id": "confidentiality_fr",
|
|
36
|
+
"strength": 0.9,
|
|
37
|
+
"flags": "i",
|
|
38
|
+
"pattern": "(Ce message .{0,60}confidentiel|destin. (exclusivement|uniquement) aux personnes)"
|
|
39
|
+
},
|
|
40
|
+
{
|
|
41
|
+
"id": "confidentiality_es",
|
|
42
|
+
"strength": 0.9,
|
|
43
|
+
"flags": "i",
|
|
44
|
+
"pattern": "(Este mensaje .{0,60}confidencial|informaci.n confidencial|destinatario)"
|
|
45
|
+
},
|
|
46
|
+
{
|
|
47
|
+
"id": "gdpr_notice",
|
|
48
|
+
"strength": 0.7,
|
|
49
|
+
"flags": "i",
|
|
50
|
+
"pattern": "(privacy (notice|policy)|processes? your personal data|GDPR|isikuandmete töötlemise)"
|
|
51
|
+
},
|
|
52
|
+
{
|
|
53
|
+
"id": "company_registration",
|
|
54
|
+
"strength": 0.6,
|
|
55
|
+
"flags": "i",
|
|
56
|
+
"pattern": "(registered (in|office) .{0,60}(no|number)\\.?\\s*[0-9]|VAT (registration )?(no|number)|Handelsregister|Reg\\.?\\s*nr\\.?\\s*[0-9])"
|
|
57
|
+
},
|
|
58
|
+
{
|
|
59
|
+
"id": "unsubscribe_footer",
|
|
60
|
+
"strength": 0.8,
|
|
61
|
+
"flags": "i",
|
|
62
|
+
"pattern": "(unsubscribe|opt out of these emails|manage your (email )?preferences|loobu (uudiskirjast|teavitustest))"
|
|
63
|
+
},
|
|
64
|
+
{
|
|
65
|
+
"id": "confidentiality_et",
|
|
66
|
+
"strength": 0.9,
|
|
67
|
+
"flags": "i",
|
|
68
|
+
"pattern": "(Käesolev (e-?kiri|sõnum) .{0,60}(konfidentsiaal|asutusesisene)|kui te ei ole .{0,40}saaja)"
|
|
69
|
+
},
|
|
70
|
+
{
|
|
71
|
+
"id": "automated_do_not_reply",
|
|
72
|
+
"strength": 0.85,
|
|
73
|
+
"flags": "i",
|
|
74
|
+
"comment": "Standard notification preamble or footer.",
|
|
75
|
+
"pattern": "(this is an? (automated|automatic|system.generated) (e-?mail|message|notification)|please do not reply to this (e-?mail|message)|do not reply directly to this)"
|
|
76
|
+
},
|
|
77
|
+
{
|
|
78
|
+
"id": "receiving_because",
|
|
79
|
+
"strength": 0.85,
|
|
80
|
+
"flags": "i",
|
|
81
|
+
"comment": "The canonical notification footer: why you got this and how to stop it. Recurs across almost every service.",
|
|
82
|
+
"pattern": "(you (are |have )?receiv(ed|ing) (this|these) .{0,60}(because|since|as (a|an) )|you'?re receiving (this|these) .{0,60}(because|since))"
|
|
83
|
+
},
|
|
84
|
+
{
|
|
85
|
+
"id": "manage_notification_preferences",
|
|
86
|
+
"strength": 0.8,
|
|
87
|
+
"flags": "i",
|
|
88
|
+
"comment": "Opt out and preference management, distinct from a plain unsubscribe link.",
|
|
89
|
+
"pattern": "(to (stop|change|update|manage|adjust) (receiving |getting )?(these|this|your) .{0,50}(e-?mails?|notifications?|messages?|preferences|settings)|(change|manage|update) your (e-?mail |notification )?(preferences|settings|subscription))"
|
|
90
|
+
},
|
|
91
|
+
{
|
|
92
|
+
"id": "subscribe_invitation_footer",
|
|
93
|
+
"strength": 0.7,
|
|
94
|
+
"flags": "i",
|
|
95
|
+
"comment": "Standing promotional footer on a notification: an invitation to subscribe to something other than what the message is about.",
|
|
96
|
+
"pattern": "(want to (know|hear|stay|learn) .{0,80}\\?\\s*(would you|subscribe|sign up|join)|would you like to (stay|be) (up.to.date|informed|notified) .{0,60}\\?)"
|
|
97
|
+
},
|
|
98
|
+
{
|
|
99
|
+
"id": "powered_by_footer",
|
|
100
|
+
"strength": 0.7,
|
|
101
|
+
"flags": "i",
|
|
102
|
+
"comment": "Provider branding appended by the sending platform.",
|
|
103
|
+
"pattern": "(powered by [A-Z]|sent (via|with|using) [A-Z][\\w.]{2,}|delivered by [A-Z][\\w.]{2,})"
|
|
104
|
+
},
|
|
105
|
+
{
|
|
106
|
+
"id": "support_contact_footer",
|
|
107
|
+
"strength": 0.6,
|
|
108
|
+
"flags": "i",
|
|
109
|
+
"comment": "Standing support or help pointer in a service footer.",
|
|
110
|
+
"pattern": "(if you (have any )?(questions|need help|require assistance)[^.]{0,60}(contact|reach|e-?mail) (us|our|the) (support|team|help)|visit our (help|support) (cent(er|re)|site|page))"
|
|
111
|
+
}
|
|
112
|
+
]
|
|
113
|
+
}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
{
|
|
2
|
+
"description": "Markers introducing intentionally forwarded content. Forwarded material is preserved as structured, collapsible content and is never dropped, so these patterns open a FORWARDED_CONTENT region rather than a hidden one.",
|
|
3
|
+
"patterns": [
|
|
4
|
+
{
|
|
5
|
+
"id": "begin_forwarded_message",
|
|
6
|
+
"lang": "*",
|
|
7
|
+
"strength": 0.97,
|
|
8
|
+
"flags": "i",
|
|
9
|
+
"pattern": "^\\s*Begin forwarded message\\s*:?\\s*$"
|
|
10
|
+
},
|
|
11
|
+
{
|
|
12
|
+
"id": "forwarded_message_dashes",
|
|
13
|
+
"lang": "*",
|
|
14
|
+
"strength": 0.97,
|
|
15
|
+
"flags": "i",
|
|
16
|
+
"pattern": "^\\s*-{2,}\\s*Forwarded message\\s*-{2,}\\s*$"
|
|
17
|
+
},
|
|
18
|
+
{
|
|
19
|
+
"id": "forwarded_message_localised",
|
|
20
|
+
"lang": "*",
|
|
21
|
+
"strength": 0.95,
|
|
22
|
+
"flags": "i",
|
|
23
|
+
"pattern": "^\\s*-{2,}\\s*(Weitergeleitete Nachricht|Message transf.r.|Mensaje reenviado|Messaggio inoltrato|Doorgestuurd bericht|Edastatud kiri|Edasisaadetud (sõnumi|kirja).{0,20}|Пересылаемое сообщение)\\s*-{2,}\\s*$"
|
|
24
|
+
},
|
|
25
|
+
{
|
|
26
|
+
"id": "original_message_forward",
|
|
27
|
+
"lang": "*",
|
|
28
|
+
"strength": 0.9,
|
|
29
|
+
"flags": "i",
|
|
30
|
+
"pattern": "^\\s*-{2,}\\s*Forwarded by\\b.{0,120}$"
|
|
31
|
+
},
|
|
32
|
+
{
|
|
33
|
+
"id": "fyi_forward_header_block",
|
|
34
|
+
"lang": "*",
|
|
35
|
+
"strength": 0.7,
|
|
36
|
+
"flags": "i",
|
|
37
|
+
"pattern": "^\\s*(From|Van|Von|De|Da|Fra|Kellelt|От)\\s*:\\s*.{1,300}$"
|
|
38
|
+
}
|
|
39
|
+
]
|
|
40
|
+
}
|
|
@@ -0,0 +1,157 @@
|
|
|
1
|
+
{
|
|
2
|
+
"description": "Client specific HTML structures, expressed as CSS selectors. Prevalence figures are measured on human authored replies in the working corpus and drive the priority order. Each entry declares a role: 'quote' encloses history, 'separator' means everything after it in document order is history, 'signature' and 'disclaimer' mark trailing footers, and 'new' marks containers a client uses for freshly typed text.",
|
|
3
|
+
"selectors": [
|
|
4
|
+
{
|
|
5
|
+
"id": "gmail_quote",
|
|
6
|
+
"client": "gmail",
|
|
7
|
+
"role": "quote",
|
|
8
|
+
"strength": 0.95,
|
|
9
|
+
"selector": ".gmail_quote",
|
|
10
|
+
"prevalence": 0.51
|
|
11
|
+
},
|
|
12
|
+
{
|
|
13
|
+
"id": "gmail_quote_container",
|
|
14
|
+
"client": "gmail",
|
|
15
|
+
"role": "quote",
|
|
16
|
+
"strength": 0.95,
|
|
17
|
+
"selector": ".gmail_quote_container",
|
|
18
|
+
"prevalence": 0.2
|
|
19
|
+
},
|
|
20
|
+
{
|
|
21
|
+
"id": "gmail_attr",
|
|
22
|
+
"client": "gmail",
|
|
23
|
+
"role": "attribution",
|
|
24
|
+
"strength": 0.92,
|
|
25
|
+
"selector": ".gmail_attr",
|
|
26
|
+
"prevalence": 0.47
|
|
27
|
+
},
|
|
28
|
+
{
|
|
29
|
+
"id": "gmail_signature",
|
|
30
|
+
"client": "gmail",
|
|
31
|
+
"role": "signature",
|
|
32
|
+
"strength": 0.9,
|
|
33
|
+
"selector": ".gmail_signature",
|
|
34
|
+
"prevalence": 0.27
|
|
35
|
+
},
|
|
36
|
+
{
|
|
37
|
+
"id": "owa_reply_separator",
|
|
38
|
+
"client": "outlook-web",
|
|
39
|
+
"role": "separator",
|
|
40
|
+
"strength": 0.95,
|
|
41
|
+
"selector": "div#divRplyFwdMsg",
|
|
42
|
+
"prevalence": 0.26
|
|
43
|
+
},
|
|
44
|
+
{
|
|
45
|
+
"id": "owa_append_on_send",
|
|
46
|
+
"client": "outlook-web",
|
|
47
|
+
"role": "separator",
|
|
48
|
+
"strength": 0.85,
|
|
49
|
+
"selector": "div#appendonsend",
|
|
50
|
+
"prevalence": 0.1
|
|
51
|
+
},
|
|
52
|
+
{
|
|
53
|
+
"id": "owa_element_to_proof",
|
|
54
|
+
"client": "outlook-web",
|
|
55
|
+
"role": "new",
|
|
56
|
+
"strength": 0.7,
|
|
57
|
+
"selector": ".elementToProof",
|
|
58
|
+
"prevalence": 0.12
|
|
59
|
+
},
|
|
60
|
+
{
|
|
61
|
+
"id": "outlook_mso_normal",
|
|
62
|
+
"client": "outlook-desktop",
|
|
63
|
+
"role": "hint",
|
|
64
|
+
"strength": 0.5,
|
|
65
|
+
"selector": "p.MsoNormal",
|
|
66
|
+
"prevalence": 0.16
|
|
67
|
+
},
|
|
68
|
+
{
|
|
69
|
+
"id": "outlook_word_section",
|
|
70
|
+
"client": "outlook-desktop",
|
|
71
|
+
"role": "hint",
|
|
72
|
+
"strength": 0.5,
|
|
73
|
+
"selector": "div.WordSection1",
|
|
74
|
+
"prevalence": 0.13
|
|
75
|
+
},
|
|
76
|
+
{
|
|
77
|
+
"id": "apple_mail_cite",
|
|
78
|
+
"client": "apple-mail",
|
|
79
|
+
"role": "quote",
|
|
80
|
+
"strength": 0.9,
|
|
81
|
+
"selector": "blockquote[type=cite]",
|
|
82
|
+
"prevalence": 0.04
|
|
83
|
+
},
|
|
84
|
+
{
|
|
85
|
+
"id": "apple_interchange_newline",
|
|
86
|
+
"client": "apple-mail",
|
|
87
|
+
"role": "hint",
|
|
88
|
+
"strength": 0.6,
|
|
89
|
+
"selector": "br.Apple-interchange-newline",
|
|
90
|
+
"prevalence": 0.04
|
|
91
|
+
},
|
|
92
|
+
{
|
|
93
|
+
"id": "thunderbird_moz_cite",
|
|
94
|
+
"client": "thunderbird",
|
|
95
|
+
"role": "attribution",
|
|
96
|
+
"strength": 0.95,
|
|
97
|
+
"selector": ".moz-cite-prefix",
|
|
98
|
+
"prevalence": 0.008
|
|
99
|
+
},
|
|
100
|
+
{
|
|
101
|
+
"id": "thunderbird_signature",
|
|
102
|
+
"client": "thunderbird",
|
|
103
|
+
"role": "signature",
|
|
104
|
+
"strength": 0.9,
|
|
105
|
+
"selector": "div.moz-signature",
|
|
106
|
+
"prevalence": 0.005
|
|
107
|
+
},
|
|
108
|
+
{
|
|
109
|
+
"id": "proton_quote",
|
|
110
|
+
"client": "proton",
|
|
111
|
+
"role": "quote",
|
|
112
|
+
"strength": 0.95,
|
|
113
|
+
"selector": ".protonmail_quote",
|
|
114
|
+
"prevalence": 0.002
|
|
115
|
+
},
|
|
116
|
+
{
|
|
117
|
+
"id": "proton_signature",
|
|
118
|
+
"client": "proton",
|
|
119
|
+
"role": "signature",
|
|
120
|
+
"strength": 0.9,
|
|
121
|
+
"selector": "div.protonmail_signature_block",
|
|
122
|
+
"prevalence": 0.002
|
|
123
|
+
},
|
|
124
|
+
{
|
|
125
|
+
"id": "yahoo_quoted",
|
|
126
|
+
"client": "yahoo",
|
|
127
|
+
"role": "quote",
|
|
128
|
+
"strength": 0.95,
|
|
129
|
+
"selector": ".yahoo_quoted",
|
|
130
|
+
"prevalence": 0.002
|
|
131
|
+
},
|
|
132
|
+
{
|
|
133
|
+
"id": "zimbra_separator",
|
|
134
|
+
"client": "zimbra",
|
|
135
|
+
"role": "separator",
|
|
136
|
+
"strength": 0.9,
|
|
137
|
+
"selector": "hr#zwchr",
|
|
138
|
+
"prevalence": 0.001
|
|
139
|
+
},
|
|
140
|
+
{
|
|
141
|
+
"id": "roundcube_quote",
|
|
142
|
+
"client": "roundcube",
|
|
143
|
+
"role": "quote",
|
|
144
|
+
"strength": 0.85,
|
|
145
|
+
"selector": "blockquote.reply",
|
|
146
|
+
"prevalence": 0.001
|
|
147
|
+
},
|
|
148
|
+
{
|
|
149
|
+
"id": "generic_blockquote",
|
|
150
|
+
"client": "*",
|
|
151
|
+
"role": "quote",
|
|
152
|
+
"strength": 0.6,
|
|
153
|
+
"selector": "blockquote",
|
|
154
|
+
"prevalence": 0.44
|
|
155
|
+
}
|
|
156
|
+
]
|
|
157
|
+
}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
{
|
|
2
|
+
"description": "Field names of an embedded copy of a previous message's headers, as Outlook and several webmail clients emit above quoted history. A single line matching one of these is weak evidence on its own, because ordinary prose can start with 'From:'. Two or more of these in consecutive lines, including at least one of the date-like fields, is a strong anchor. The consecutive-line rule lives in the detector, not here.",
|
|
3
|
+
"fields": [
|
|
4
|
+
{
|
|
5
|
+
"id": "from",
|
|
6
|
+
"role": "originator",
|
|
7
|
+
"flags": "i",
|
|
8
|
+
"pattern": "^\\s*(From|De|Von|Van|Da|Fra|Från|Lähettäjä|Kellelt|Saatja|От|Od|Nadawca|Remetente)\\s*:\\s*\\S"
|
|
9
|
+
},
|
|
10
|
+
{
|
|
11
|
+
"id": "sent",
|
|
12
|
+
"role": "date",
|
|
13
|
+
"flags": "i",
|
|
14
|
+
"pattern": "^\\s*(Sent|Date|Datum|Envoy.|Enviado|Inviato|Verzonden|Skickat|Lähetetty|Saadetud|Kuupäev|Отправлено|Дата|Wysłano|Data)\\s*:\\s*\\S"
|
|
15
|
+
},
|
|
16
|
+
{
|
|
17
|
+
"id": "to",
|
|
18
|
+
"role": "recipient",
|
|
19
|
+
"flags": "i",
|
|
20
|
+
"pattern": "^\\s*(To|A|An|Aan|Para|À|Till|Vastaanottaja|Kellele|Saaja|Кому|Do|Adresat)\\s*:\\s*\\S"
|
|
21
|
+
},
|
|
22
|
+
{
|
|
23
|
+
"id": "cc",
|
|
24
|
+
"role": "recipient",
|
|
25
|
+
"flags": "i",
|
|
26
|
+
"pattern": "^\\s*(Cc|CC|Copie|Kopie|Koopia|Kopio|Копия|DW)\\s*:\\s*\\S"
|
|
27
|
+
},
|
|
28
|
+
{
|
|
29
|
+
"id": "subject",
|
|
30
|
+
"role": "subject",
|
|
31
|
+
"flags": "i",
|
|
32
|
+
"pattern": "^\\s*(Subject|Betreff|Objet|Asunto|Oggetto|Onderwerp|Ämne|Aihe|Teema|Teated|Тема|Temat|Assunto)\\s*:\\s*\\S"
|
|
33
|
+
},
|
|
34
|
+
{
|
|
35
|
+
"id": "reply_to",
|
|
36
|
+
"role": "originator",
|
|
37
|
+
"flags": "i",
|
|
38
|
+
"pattern": "^\\s*(Reply-To|Antwort an|Répondre à)\\s*:\\s*\\S"
|
|
39
|
+
}
|
|
40
|
+
]
|
|
41
|
+
}
|
|
@@ -0,0 +1,139 @@
|
|
|
1
|
+
{
|
|
2
|
+
"description": "Attribution lines that a mail client inserts above quoted reply history. Matching one of these is a structural anchor: it is the strongest single piece of evidence that everything following is embedded history rather than new content. Patterns are matched per line against the canonicalised plain text projection.",
|
|
3
|
+
"patterns": [
|
|
4
|
+
{
|
|
5
|
+
"id": "on_x_wrote_en",
|
|
6
|
+
"lang": "en",
|
|
7
|
+
"strength": 0.95,
|
|
8
|
+
"flags": "i",
|
|
9
|
+
"pattern": "^\\s*On\\s+.{3,200}?\\bwrote\\s*:\\s*$"
|
|
10
|
+
},
|
|
11
|
+
{
|
|
12
|
+
"id": "on_x_wrote_en_wrapped",
|
|
13
|
+
"lang": "en",
|
|
14
|
+
"comment": "Attribution line whose trailing 'wrote:' was wrapped onto the next line. Requires a date or clock time so that ordinary sentences beginning with 'On ' do not match, and is scored well below an anchor because it cannot be trusted alone. Measured firing on 10.4 percent of the corpus before the date requirement was added.",
|
|
15
|
+
"strength": 0.5,
|
|
16
|
+
"flags": "i",
|
|
17
|
+
"pattern": "^\\s*On\\s+.{3,200}?(\\b\\d{4}\\b|\\b\\d{1,2}:\\d{2}\\b).{0,80}[,:]?\\s*$"
|
|
18
|
+
},
|
|
19
|
+
{
|
|
20
|
+
"id": "x_wrote_trailing",
|
|
21
|
+
"lang": "en",
|
|
22
|
+
"strength": 0.8,
|
|
23
|
+
"flags": "i",
|
|
24
|
+
"pattern": "^\\s*.{3,200}?\\bwrote\\s*:\\s*$"
|
|
25
|
+
},
|
|
26
|
+
{
|
|
27
|
+
"id": "at_x_wrote",
|
|
28
|
+
"lang": "en",
|
|
29
|
+
"strength": 0.9,
|
|
30
|
+
"flags": "i",
|
|
31
|
+
"pattern": "^\\s*At\\s+\\d{1,2}:\\d{2}.{0,200}?\\bwrote\\s*:\\s*$"
|
|
32
|
+
},
|
|
33
|
+
{
|
|
34
|
+
"id": "le_x_a_ecrit_fr",
|
|
35
|
+
"lang": "fr",
|
|
36
|
+
"strength": 0.95,
|
|
37
|
+
"flags": "i",
|
|
38
|
+
"pattern": "^\\s*Le\\s+.{3,200}?a\\s+.crit\\s*:\\s*$"
|
|
39
|
+
},
|
|
40
|
+
{
|
|
41
|
+
"id": "am_x_schrieb_de",
|
|
42
|
+
"lang": "de",
|
|
43
|
+
"strength": 0.95,
|
|
44
|
+
"flags": "i",
|
|
45
|
+
"pattern": "^\\s*(Am|Von)\\s+.{3,200}?schrieb.{0,60}:\\s*$"
|
|
46
|
+
},
|
|
47
|
+
{
|
|
48
|
+
"id": "el_x_escribio_es",
|
|
49
|
+
"lang": "es",
|
|
50
|
+
"strength": 0.95,
|
|
51
|
+
"flags": "i",
|
|
52
|
+
"pattern": "^\\s*El\\s+.{3,200}?escribi.{0,3}\\s*:\\s*$"
|
|
53
|
+
},
|
|
54
|
+
{
|
|
55
|
+
"id": "il_x_ha_scritto_it",
|
|
56
|
+
"lang": "it",
|
|
57
|
+
"strength": 0.95,
|
|
58
|
+
"flags": "i",
|
|
59
|
+
"pattern": "^\\s*Il\\s+.{3,200}?ha\\s+scritto\\s*:\\s*$"
|
|
60
|
+
},
|
|
61
|
+
{
|
|
62
|
+
"id": "em_x_escreveu_pt",
|
|
63
|
+
"lang": "pt",
|
|
64
|
+
"strength": 0.95,
|
|
65
|
+
"flags": "i",
|
|
66
|
+
"pattern": "^\\s*Em\\s+.{3,200}?escreveu\\s*:\\s*$"
|
|
67
|
+
},
|
|
68
|
+
{
|
|
69
|
+
"id": "op_x_schreef_nl",
|
|
70
|
+
"lang": "nl",
|
|
71
|
+
"strength": 0.95,
|
|
72
|
+
"flags": "i",
|
|
73
|
+
"pattern": "^\\s*Op\\s+.{3,200}?schreef\\s*.{0,80}:\\s*$"
|
|
74
|
+
},
|
|
75
|
+
{
|
|
76
|
+
"id": "w_dniu_x_napisal_pl",
|
|
77
|
+
"lang": "pl",
|
|
78
|
+
"strength": 0.95,
|
|
79
|
+
"flags": "i",
|
|
80
|
+
"pattern": "^\\s*W\\s+dniu\\s+.{3,200}?napisa.{1,2}\\s*.{0,40}:\\s*$"
|
|
81
|
+
},
|
|
82
|
+
{
|
|
83
|
+
"id": "x_kirjutas_et",
|
|
84
|
+
"lang": "et",
|
|
85
|
+
"strength": 0.95,
|
|
86
|
+
"flags": "i",
|
|
87
|
+
"pattern": "^\\s*.{3,200}?\\bkirjutas\\s*:\\s*$"
|
|
88
|
+
},
|
|
89
|
+
{
|
|
90
|
+
"id": "x_kirjoitti_fi",
|
|
91
|
+
"lang": "fi",
|
|
92
|
+
"strength": 0.95,
|
|
93
|
+
"flags": "i",
|
|
94
|
+
"pattern": "^\\s*.{3,200}?\\bkirjoitti\\s*:\\s*$"
|
|
95
|
+
},
|
|
96
|
+
{
|
|
97
|
+
"id": "den_x_skrev_sv",
|
|
98
|
+
"lang": "sv",
|
|
99
|
+
"strength": 0.95,
|
|
100
|
+
"flags": "i",
|
|
101
|
+
"pattern": "^\\s*(Den|.{0,60})\\s*.{3,200}?\\bskrev\\s*.{0,80}:\\s*$"
|
|
102
|
+
},
|
|
103
|
+
{
|
|
104
|
+
"id": "x_pisal_ru",
|
|
105
|
+
"lang": "ru",
|
|
106
|
+
"strength": 0.95,
|
|
107
|
+
"flags": "i",
|
|
108
|
+
"pattern": "^\\s*.{3,200}?(писал|написал)\\s*.{0,40}:\\s*$"
|
|
109
|
+
},
|
|
110
|
+
{
|
|
111
|
+
"id": "date_addr_colon",
|
|
112
|
+
"lang": "*",
|
|
113
|
+
"strength": 0.85,
|
|
114
|
+
"flags": "i",
|
|
115
|
+
"pattern": "^\\s*\\d{4}[-/]\\d{1,2}[-/]\\d{1,2}.{0,120}<[^>]+@[^>]+>.{0,40}:\\s*$"
|
|
116
|
+
},
|
|
117
|
+
{
|
|
118
|
+
"id": "original_message_separator",
|
|
119
|
+
"lang": "*",
|
|
120
|
+
"strength": 0.97,
|
|
121
|
+
"flags": "i",
|
|
122
|
+
"pattern": "^\\s*-{2,}\\s*(Original Message|Originalnachricht|Message d'origine|Mensaje original|Messaggio originale|Oorspronkelijk bericht|Algne teade|Исходное сообщение)\\s*-{2,}\\s*$"
|
|
123
|
+
},
|
|
124
|
+
{
|
|
125
|
+
"id": "reply_message_separator",
|
|
126
|
+
"lang": "*",
|
|
127
|
+
"strength": 0.95,
|
|
128
|
+
"flags": "i",
|
|
129
|
+
"pattern": "^\\s*-{2,}\\s*(Reply Message|Antwort|Svar)\\s*-{2,}\\s*$"
|
|
130
|
+
},
|
|
131
|
+
{
|
|
132
|
+
"id": "outlook_underscore_rule",
|
|
133
|
+
"lang": "*",
|
|
134
|
+
"strength": 0.6,
|
|
135
|
+
"flags": "",
|
|
136
|
+
"pattern": "^_{10,}\\s*$"
|
|
137
|
+
}
|
|
138
|
+
]
|
|
139
|
+
}
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
{
|
|
2
|
+
"description": "Signature evidence. Signatures are demoted, never deleted, so these patterns only need to be good enough to collapse a trailing block. The RFC 3676 delimiter is the only high confidence rule; everything else is positional evidence that the sequence classifier weighs.",
|
|
3
|
+
"delimiters": [
|
|
4
|
+
{
|
|
5
|
+
"id": "dash_dash_space",
|
|
6
|
+
"strength": 0.95,
|
|
7
|
+
"flags": "",
|
|
8
|
+
"pattern": "^-- ?$"
|
|
9
|
+
},
|
|
10
|
+
{
|
|
11
|
+
"id": "dash_run",
|
|
12
|
+
"strength": 0.4,
|
|
13
|
+
"flags": "",
|
|
14
|
+
"pattern": "^\\s*[-_=*~]{3,}\\s*$"
|
|
15
|
+
}
|
|
16
|
+
],
|
|
17
|
+
"phrases": [
|
|
18
|
+
{
|
|
19
|
+
"id": "sent_from_device",
|
|
20
|
+
"strength": 0.9,
|
|
21
|
+
"flags": "i",
|
|
22
|
+
"pattern": "^\\s*(Sent from|Get) (my|Outlook|BlueMail|Mail for|Yahoo Mail|Proton Mail|the) .{0,60}$"
|
|
23
|
+
},
|
|
24
|
+
{
|
|
25
|
+
"id": "sent_from_localised",
|
|
26
|
+
"strength": 0.9,
|
|
27
|
+
"flags": "i",
|
|
28
|
+
"pattern": "^\\s*(Von meinem|Envoy. de mon|Enviado desde mi|Inviato da|Verzonden vanaf mijn|Skickat från min|Lähetetty|Saadetud minu|Отправлено с) .{0,60}$"
|
|
29
|
+
},
|
|
30
|
+
{
|
|
31
|
+
"id": "best_regards",
|
|
32
|
+
"strength": 0.35,
|
|
33
|
+
"flags": "i",
|
|
34
|
+
"pattern": "^\\s*(Best regards|Kind regards|Warm regards|Best wishes|Regards|Cheers|Thanks|Thank you|Sincerely|Best|Yours( sincerely| truly)?|Mit freundlichen Grüßen|Viele Grüße|Beste Grüße|Cordialement|Bien à vous|Saludos|Atentamente|Cordiali saluti|Groeten|Met vriendelijke groet|Med vänliga hälsningar|Vänliga hälsningar|Mvh|Ystävällisin terveisin|Terveisin|Parimat|Parimate soovidega|Heade soovidega|Lugupidamisega|Tervitades|Tervitused|Terv|Kõike head|Ilusat päeva|Head aega|Austusega|С уважением|Z poważaniem|Pozdrawiam)\\s*[,.!]?\\s*$",
|
|
35
|
+
"comment": "Closing greeting. Mined from blocks the reference labelled SIGNATURE that this baseline missed, which is why the Estonian forms are here: the working corpus is roughly ten percent Estonian and those accounted for the largest group of misses."
|
|
36
|
+
},
|
|
37
|
+
{
|
|
38
|
+
"id": "contact_line",
|
|
39
|
+
"strength": 0.3,
|
|
40
|
+
"flags": "i",
|
|
41
|
+
"pattern": "^\\s*(Tel|Phone|Mobile|Mob|Fax|Cell|M|T|E|W)\\s*[:.]?\\s*[+0-9(][-0-9()\\s.]{6,}$"
|
|
42
|
+
},
|
|
43
|
+
{
|
|
44
|
+
"id": "company_registration_line",
|
|
45
|
+
"comment": "Continental European corporate footers carry a registered office and company number. These lines are boilerplate, never authored prose.",
|
|
46
|
+
"strength": 0.6,
|
|
47
|
+
"flags": "i",
|
|
48
|
+
"pattern": "^\\s*(Geschäftsführer|Handelsregister|Registergericht|Sitz der Gesellschaft|HRB\\s*\\d|USt-IdNr|VAT\\s*(No|ID)|Reg\\.?\\s*(nr|no)\\.?\\s*\\d|Registrikood|Äriregistri)"
|
|
49
|
+
},
|
|
50
|
+
{
|
|
51
|
+
"id": "postal_address_line",
|
|
52
|
+
"comment": "A street or postal code line in a trailing block. Weak on its own, but it pairs with a name or a closing greeting to identify a corporate signature.",
|
|
53
|
+
"strength": 0.4,
|
|
54
|
+
"flags": "i",
|
|
55
|
+
"pattern": "^\\s*([A-ZÄÖÜÕŠŽ][\\w.-]*\\s+)?(Str\\.|Straße|Strasse|Street|Avenue|Ave\\.|Road|Rd\\.|tee|tänav|pst)\\s*\\.?\\s*\\d|^\\s*[A-Z]{0,2}-?\\d{4,6}\\s+[A-ZÄÖÜÕ]"
|
|
56
|
+
}
|
|
57
|
+
]
|
|
58
|
+
}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Pattern set loader.
|
|
3
|
+
*
|
|
4
|
+
* Patterns live in JSON so they can be extended or overridden without touching code, which matters
|
|
5
|
+
* because the multilingual and client specific surface keeps growing. A broken pattern is skipped
|
|
6
|
+
* with a warning rather than crashing the process: a bad regex in a config file must never take
|
|
7
|
+
* down a corpus run.
|
|
8
|
+
*
|
|
9
|
+
* Set EMAIL_CONTENT_PATTERNS to a directory to override the bundled sets. Files are matched by
|
|
10
|
+
* name, so an override directory may contain only the files it wants to replace.
|
|
11
|
+
*/
|
|
12
|
+
export interface LinePattern {
|
|
13
|
+
id: string;
|
|
14
|
+
lang?: string;
|
|
15
|
+
role?: string;
|
|
16
|
+
client?: string;
|
|
17
|
+
strength: number;
|
|
18
|
+
regex: RegExp;
|
|
19
|
+
}
|
|
20
|
+
export interface SelectorPattern {
|
|
21
|
+
id: string;
|
|
22
|
+
client: string;
|
|
23
|
+
role: 'quote' | 'attribution' | 'separator' | 'signature' | 'disclaimer' | 'new' | 'hint';
|
|
24
|
+
strength: number;
|
|
25
|
+
selector: string;
|
|
26
|
+
prevalence: number;
|
|
27
|
+
}
|
|
28
|
+
export interface PatternSets {
|
|
29
|
+
replyHeaders: LinePattern[];
|
|
30
|
+
forwardHeaders: LinePattern[];
|
|
31
|
+
quotedHeaderFields: LinePattern[];
|
|
32
|
+
signatureDelimiters: LinePattern[];
|
|
33
|
+
signaturePhrases: LinePattern[];
|
|
34
|
+
disclaimerPhrases: LinePattern[];
|
|
35
|
+
htmlSelectors: SelectorPattern[];
|
|
36
|
+
/** Ids of patterns that failed to compile, for diagnostics. */
|
|
37
|
+
invalid: string[];
|
|
38
|
+
}
|
|
39
|
+
/** Load and compile all pattern sets. Cached after the first call. */
|
|
40
|
+
export declare function loadPatterns(overrideDir?: string | null): PatternSets;
|
|
41
|
+
/** Reset the cache. Used by tests that swap pattern directories. */
|
|
42
|
+
export declare function resetPatternCache(): void;
|
|
43
|
+
//# sourceMappingURL=patterns.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"patterns.d.ts","sourceRoot":"","sources":["../../src/detect/patterns.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAKH,MAAM,WAAW,WAAW;IACxB,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,eAAe;IAC5B,EAAE,EAAE,MAAM,CAAC;IACX,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,OAAO,GAAG,aAAa,GAAG,WAAW,GAAG,WAAW,GAAG,YAAY,GAAG,KAAK,GAAG,MAAM,CAAC;IAC1F,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,MAAM,CAAC;IACjB,UAAU,EAAE,MAAM,CAAC;CACtB;AAED,MAAM,WAAW,WAAW;IACxB,YAAY,EAAE,WAAW,EAAE,CAAC;IAC5B,cAAc,EAAE,WAAW,EAAE,CAAC;IAC9B,kBAAkB,EAAE,WAAW,EAAE,CAAC;IAClC,mBAAmB,EAAE,WAAW,EAAE,CAAC;IACnC,gBAAgB,EAAE,WAAW,EAAE,CAAC;IAChC,iBAAiB,EAAE,WAAW,EAAE,CAAC;IACjC,aAAa,EAAE,eAAe,EAAE,CAAC;IACjC,+DAA+D;IAC/D,OAAO,EAAE,MAAM,EAAE,CAAC;CACrB;AAwFD,sEAAsE;AACtE,wBAAgB,YAAY,CAAC,WAAW,CAAC,EAAE,MAAM,GAAG,IAAI,GAAG,WAAW,CA6BrE;AAED,oEAAoE;AACpE,wBAAgB,iBAAiB,IAAI,IAAI,CAExC"}
|