@nathanvale/chatline 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/CHANGELOG.md +1 -0
- package/LICENSE +21 -0
- package/README.md +1535 -0
- package/dist/bin/index.js +5121 -0
- package/dist/cli/commands/clean.d.ts +17 -0
- package/dist/cli/commands/clean.d.ts.map +1 -0
- package/dist/cli/commands/clean.js +142 -0
- package/dist/cli/commands/clean.js.map +1 -0
- package/dist/cli/commands/doctor.d.ts +17 -0
- package/dist/cli/commands/doctor.d.ts.map +1 -0
- package/dist/cli/commands/doctor.js +202 -0
- package/dist/cli/commands/doctor.js.map +1 -0
- package/dist/cli/commands/enrich-ai.d.ts +17 -0
- package/dist/cli/commands/enrich-ai.d.ts.map +1 -0
- package/dist/cli/commands/enrich-ai.js +371 -0
- package/dist/cli/commands/enrich-ai.js.map +1 -0
- package/dist/cli/commands/index.d.ts +16 -0
- package/dist/cli/commands/index.d.ts.map +1 -0
- package/dist/cli/commands/index.js +16 -0
- package/dist/cli/commands/index.js.map +1 -0
- package/dist/cli/commands/ingest-csv.d.ts +17 -0
- package/dist/cli/commands/ingest-csv.d.ts.map +1 -0
- package/dist/cli/commands/ingest-csv.js +138 -0
- package/dist/cli/commands/ingest-csv.js.map +1 -0
- package/dist/cli/commands/ingest-db.d.ts +17 -0
- package/dist/cli/commands/ingest-db.d.ts.map +1 -0
- package/dist/cli/commands/ingest-db.js +159 -0
- package/dist/cli/commands/ingest-db.js.map +1 -0
- package/dist/cli/commands/init.d.ts +17 -0
- package/dist/cli/commands/init.d.ts.map +1 -0
- package/dist/cli/commands/init.js +110 -0
- package/dist/cli/commands/init.js.map +1 -0
- package/dist/cli/commands/normalize-link.d.ts +16 -0
- package/dist/cli/commands/normalize-link.d.ts.map +1 -0
- package/dist/cli/commands/normalize-link.js +144 -0
- package/dist/cli/commands/normalize-link.js.map +1 -0
- package/dist/cli/commands/render-markdown.d.ts +17 -0
- package/dist/cli/commands/render-markdown.d.ts.map +1 -0
- package/dist/cli/commands/render-markdown.js +218 -0
- package/dist/cli/commands/render-markdown.js.map +1 -0
- package/dist/cli/commands/stats.d.ts +17 -0
- package/dist/cli/commands/stats.d.ts.map +1 -0
- package/dist/cli/commands/stats.js +175 -0
- package/dist/cli/commands/stats.js.map +1 -0
- package/dist/cli/commands/validate.d.ts +17 -0
- package/dist/cli/commands/validate.d.ts.map +1 -0
- package/dist/cli/commands/validate.js +152 -0
- package/dist/cli/commands/validate.js.map +1 -0
- package/dist/cli/index.d.ts +13 -0
- package/dist/cli/index.d.ts.map +1 -0
- package/dist/cli/index.js +121 -0
- package/dist/cli/index.js.map +1 -0
- package/dist/cli/types.d.ts +93 -0
- package/dist/cli/types.d.ts.map +1 -0
- package/dist/cli/types.js +7 -0
- package/dist/cli/types.js.map +1 -0
- package/dist/cli/utils.d.ts +29 -0
- package/dist/cli/utils.d.ts.map +1 -0
- package/dist/cli/utils.js +53 -0
- package/dist/cli/utils.js.map +1 -0
- package/dist/cli.d.ts +9 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +1805 -0
- package/dist/config/generator.d.ts +90 -0
- package/dist/config/generator.d.ts.map +1 -0
- package/dist/config/generator.js +320 -0
- package/dist/config/generator.js.map +1 -0
- package/dist/config/loader.d.ts +107 -0
- package/dist/config/loader.d.ts.map +1 -0
- package/dist/config/loader.js +251 -0
- package/dist/config/loader.js.map +1 -0
- package/dist/config/schema.d.ts +107 -0
- package/dist/config/schema.d.ts.map +1 -0
- package/dist/config/schema.js +169 -0
- package/dist/config/schema.js.map +1 -0
- package/dist/enrich/audio-transcription.d.ts +77 -0
- package/dist/enrich/audio-transcription.d.ts.map +1 -0
- package/dist/enrich/audio-transcription.js +370 -0
- package/dist/enrich/audio-transcription.js.map +1 -0
- package/dist/enrich/checkpoint.d.ts +137 -0
- package/dist/enrich/checkpoint.d.ts.map +1 -0
- package/dist/enrich/checkpoint.js +205 -0
- package/dist/enrich/checkpoint.js.map +1 -0
- package/dist/enrich/idempotency.d.ts +90 -0
- package/dist/enrich/idempotency.d.ts.map +1 -0
- package/dist/enrich/idempotency.js +188 -0
- package/dist/enrich/idempotency.js.map +1 -0
- package/dist/enrich/image-analysis.d.ts +62 -0
- package/dist/enrich/image-analysis.d.ts.map +1 -0
- package/dist/enrich/image-analysis.js +264 -0
- package/dist/enrich/image-analysis.js.map +1 -0
- package/dist/enrich/index.d.ts +60 -0
- package/dist/enrich/index.d.ts.map +1 -0
- package/dist/enrich/index.js +74 -0
- package/dist/enrich/index.js.map +1 -0
- package/dist/enrich/link-enrichment.d.ts +37 -0
- package/dist/enrich/link-enrichment.d.ts.map +1 -0
- package/dist/enrich/link-enrichment.js +202 -0
- package/dist/enrich/link-enrichment.js.map +1 -0
- package/dist/enrich/pdf-video-handling.d.ts +49 -0
- package/dist/enrich/pdf-video-handling.d.ts.map +1 -0
- package/dist/enrich/pdf-video-handling.js +325 -0
- package/dist/enrich/pdf-video-handling.js.map +1 -0
- package/dist/enrich/progress-tracker.d.ts +120 -0
- package/dist/enrich/progress-tracker.d.ts.map +1 -0
- package/dist/enrich/progress-tracker.js +220 -0
- package/dist/enrich/progress-tracker.js.map +1 -0
- package/dist/enrich/providers/firecrawl.d.ts +18 -0
- package/dist/enrich/providers/firecrawl.d.ts.map +1 -0
- package/dist/enrich/providers/firecrawl.js +48 -0
- package/dist/enrich/providers/firecrawl.js.map +1 -0
- package/dist/enrich/providers/generic.d.ts +16 -0
- package/dist/enrich/providers/generic.d.ts.map +1 -0
- package/dist/enrich/providers/generic.js +36 -0
- package/dist/enrich/providers/generic.js.map +1 -0
- package/dist/enrich/providers/index.d.ts +14 -0
- package/dist/enrich/providers/index.d.ts.map +1 -0
- package/dist/enrich/providers/index.js +13 -0
- package/dist/enrich/providers/index.js.map +1 -0
- package/dist/enrich/providers/instagram.d.ts +16 -0
- package/dist/enrich/providers/instagram.d.ts.map +1 -0
- package/dist/enrich/providers/instagram.js +43 -0
- package/dist/enrich/providers/instagram.js.map +1 -0
- package/dist/enrich/providers/spotify.d.ts +16 -0
- package/dist/enrich/providers/spotify.d.ts.map +1 -0
- package/dist/enrich/providers/spotify.js +45 -0
- package/dist/enrich/providers/spotify.js.map +1 -0
- package/dist/enrich/providers/twitter.d.ts +16 -0
- package/dist/enrich/providers/twitter.d.ts.map +1 -0
- package/dist/enrich/providers/twitter.js +43 -0
- package/dist/enrich/providers/twitter.js.map +1 -0
- package/dist/enrich/providers/types.d.ts +47 -0
- package/dist/enrich/providers/types.d.ts.map +1 -0
- package/dist/enrich/providers/types.js +15 -0
- package/dist/enrich/providers/types.js.map +1 -0
- package/dist/enrich/providers/youtube.d.ts +16 -0
- package/dist/enrich/providers/youtube.d.ts.map +1 -0
- package/dist/enrich/providers/youtube.js +43 -0
- package/dist/enrich/providers/youtube.js.map +1 -0
- package/dist/enrich/rate-limiting.d.ts +118 -0
- package/dist/enrich/rate-limiting.d.ts.map +1 -0
- package/dist/enrich/rate-limiting.js +258 -0
- package/dist/enrich/rate-limiting.js.map +1 -0
- package/dist/index.d.ts +688 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +1729 -0
- package/dist/index.js.map +1 -0
- package/dist/ingest/dedup-merge.d.ts +82 -0
- package/dist/ingest/dedup-merge.d.ts.map +1 -0
- package/dist/ingest/dedup-merge.js +262 -0
- package/dist/ingest/dedup-merge.js.map +1 -0
- package/dist/ingest/ingest-csv.d.ts +62 -0
- package/dist/ingest/ingest-csv.d.ts.map +1 -0
- package/dist/ingest/ingest-csv.js +300 -0
- package/dist/ingest/ingest-csv.js.map +1 -0
- package/dist/ingest/ingest-db.d.ts +64 -0
- package/dist/ingest/ingest-db.d.ts.map +1 -0
- package/dist/ingest/ingest-db.js +172 -0
- package/dist/ingest/ingest-db.js.map +1 -0
- package/dist/ingest/link-replies-and-tapbacks.d.ts +53 -0
- package/dist/ingest/link-replies-and-tapbacks.d.ts.map +1 -0
- package/dist/ingest/link-replies-and-tapbacks.js +381 -0
- package/dist/ingest/link-replies-and-tapbacks.js.map +1 -0
- package/dist/normalize/date-converters.d.ts +45 -0
- package/dist/normalize/date-converters.d.ts.map +1 -0
- package/dist/normalize/date-converters.js +166 -0
- package/dist/normalize/date-converters.js.map +1 -0
- package/dist/normalize/path-validator.d.ts +65 -0
- package/dist/normalize/path-validator.d.ts.map +1 -0
- package/dist/normalize/path-validator.js +221 -0
- package/dist/normalize/path-validator.js.map +1 -0
- package/dist/normalize/validate-normalized.d.ts +45 -0
- package/dist/normalize/validate-normalized.d.ts.map +1 -0
- package/dist/normalize/validate-normalized.js +144 -0
- package/dist/normalize/validate-normalized.js.map +1 -0
- package/dist/render/embeds-blockquotes.d.ts +84 -0
- package/dist/render/embeds-blockquotes.d.ts.map +1 -0
- package/dist/render/embeds-blockquotes.js +204 -0
- package/dist/render/embeds-blockquotes.js.map +1 -0
- package/dist/render/grouping.d.ts +78 -0
- package/dist/render/grouping.d.ts.map +1 -0
- package/dist/render/grouping.js +134 -0
- package/dist/render/grouping.js.map +1 -0
- package/dist/render/index.d.ts +47 -0
- package/dist/render/index.d.ts.map +1 -0
- package/dist/render/index.js +245 -0
- package/dist/render/index.js.map +1 -0
- package/dist/render/reply-rendering.d.ts +88 -0
- package/dist/render/reply-rendering.d.ts.map +1 -0
- package/dist/render/reply-rendering.js +196 -0
- package/dist/render/reply-rendering.js.map +1 -0
- package/dist/schema/message.d.ts +125 -0
- package/dist/schema/message.d.ts.map +1 -0
- package/dist/schema/message.js +331 -0
- package/dist/schema/message.js.map +1 -0
- package/dist/utils/delta-detection.d.ts +107 -0
- package/dist/utils/delta-detection.d.ts.map +1 -0
- package/dist/utils/delta-detection.js +199 -0
- package/dist/utils/delta-detection.js.map +1 -0
- package/dist/utils/enrichment-merge.d.ts +135 -0
- package/dist/utils/enrichment-merge.d.ts.map +1 -0
- package/dist/utils/enrichment-merge.js +280 -0
- package/dist/utils/enrichment-merge.js.map +1 -0
- package/dist/utils/human.d.ts +15 -0
- package/dist/utils/human.d.ts.map +1 -0
- package/dist/utils/human.js +27 -0
- package/dist/utils/human.js.map +1 -0
- package/dist/utils/incremental-state.d.ts +133 -0
- package/dist/utils/incremental-state.d.ts.map +1 -0
- package/dist/utils/incremental-state.js +237 -0
- package/dist/utils/incremental-state.js.map +1 -0
- package/dist/utils/logger.d.ts +40 -0
- package/dist/utils/logger.d.ts.map +1 -0
- package/dist/utils/logger.js +176 -0
- package/dist/utils/logger.js.map +1 -0
- package/package.json +165 -0
|
@@ -0,0 +1,204 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Embeds and Blockquotes Rendering Module (RENDER--T03)
|
|
3
|
+
*
|
|
4
|
+
* Implements Obsidian-friendly embeds and blockquote rendering:
|
|
5
|
+
* - AC01: Image embeds with ![[path]] syntax
|
|
6
|
+
* - AC02: Preview images with links to originals (HEIC/TIFF)
|
|
7
|
+
* - AC03: Transcription blockquotes with speaker labels
|
|
8
|
+
* - AC04: Link context blockquotes with metadata
|
|
9
|
+
* - AC05: PDF summary blockquotes with formatting
|
|
10
|
+
*/
|
|
11
|
+
/**
|
|
12
|
+
* AC01: Render image embed with Obsidian wikilink syntax
|
|
13
|
+
* Format: ![[path]]
|
|
14
|
+
*/
|
|
15
|
+
export function renderImageEmbed(path) {
|
|
16
|
+
return `![[${path}]]`;
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* AC02: Render preview image with link to original
|
|
20
|
+
* For HEIC/TIFF files, shows preview with link to original
|
|
21
|
+
*/
|
|
22
|
+
export function renderPreviewImageWithLink(previewPath, originalPath) {
|
|
23
|
+
const filename = originalPath.split('/').pop() || 'original';
|
|
24
|
+
return `![[${previewPath}]]\n[Original: ${filename}](${originalPath})`;
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* AC03: Render transcription as blockquote
|
|
28
|
+
* Handles multiline transcriptions with speaker labels and timestamps
|
|
29
|
+
*/
|
|
30
|
+
export function renderTranscriptionBlockquote(enrichment) {
|
|
31
|
+
if (enrichment.kind !== 'transcription' || !enrichment.transcription) {
|
|
32
|
+
return '';
|
|
33
|
+
}
|
|
34
|
+
const lines = enrichment.transcription.split('\n');
|
|
35
|
+
return lines.map((line) => `> ${line}`).join('\n');
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* AC04: Render link context as blockquote
|
|
39
|
+
* Shows title as markdown link and summary as blockquote
|
|
40
|
+
*/
|
|
41
|
+
export function renderLinkContextBlockquote(enrichment) {
|
|
42
|
+
if (enrichment.kind !== 'link_context') {
|
|
43
|
+
return '';
|
|
44
|
+
}
|
|
45
|
+
const parts = [];
|
|
46
|
+
// Format title as markdown link if available
|
|
47
|
+
if (enrichment.title && enrichment.url) {
|
|
48
|
+
parts.push(`> [${enrichment.title}](${enrichment.url})`);
|
|
49
|
+
}
|
|
50
|
+
else if (enrichment.url) {
|
|
51
|
+
parts.push(`> [${enrichment.url}](${enrichment.url})`);
|
|
52
|
+
}
|
|
53
|
+
// Add summary as blockquote lines
|
|
54
|
+
if (enrichment.summary) {
|
|
55
|
+
const summaryLines = enrichment.summary.split('\n');
|
|
56
|
+
for (const line of summaryLines) {
|
|
57
|
+
if (line.trim()) {
|
|
58
|
+
parts.push(`> ${line}`);
|
|
59
|
+
}
|
|
60
|
+
else {
|
|
61
|
+
parts.push('> ');
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
return parts.join('\n');
|
|
66
|
+
}
|
|
67
|
+
/**
|
|
68
|
+
* AC05: Render PDF summary as blockquote
|
|
69
|
+
* Preserves paragraph structure with blockquote formatting
|
|
70
|
+
*/
|
|
71
|
+
export function renderPdfSummaryBlockquote(enrichment) {
|
|
72
|
+
if (enrichment.kind !== 'pdf_summary' || !enrichment.pdfSummary) {
|
|
73
|
+
return '';
|
|
74
|
+
}
|
|
75
|
+
const lines = enrichment.pdfSummary.split('\n');
|
|
76
|
+
return lines.map((line) => `> ${line}`).join('\n');
|
|
77
|
+
}
|
|
78
|
+
/**
|
|
79
|
+
* Determine if a message should render an embed
|
|
80
|
+
* Only renders embeds for image media
|
|
81
|
+
*/
|
|
82
|
+
export function shouldRenderEmbed(message) {
|
|
83
|
+
if (message.messageKind !== 'media' || !message.media) {
|
|
84
|
+
return false;
|
|
85
|
+
}
|
|
86
|
+
// Only embed images
|
|
87
|
+
return message.media.mediaKind === 'image';
|
|
88
|
+
}
|
|
89
|
+
/**
|
|
90
|
+
* Get the path to embed for a media message
|
|
91
|
+
* Returns undefined if message cannot be embedded
|
|
92
|
+
*/
|
|
93
|
+
export function getEmbedPath(message) {
|
|
94
|
+
if (!shouldRenderEmbed(message)) {
|
|
95
|
+
return undefined;
|
|
96
|
+
}
|
|
97
|
+
return message.media?.path;
|
|
98
|
+
}
|
|
99
|
+
/**
|
|
100
|
+
* Get preview path for an image file
|
|
101
|
+
* For HEIC/TIFF, returns the .jpg preview path
|
|
102
|
+
* For JPG/PNG, returns the original path
|
|
103
|
+
*/
|
|
104
|
+
export function getPreviewPath(originalPath) {
|
|
105
|
+
const lowerPath = originalPath.toLowerCase();
|
|
106
|
+
if (lowerPath.endsWith('.heic')) {
|
|
107
|
+
return `${originalPath}.jpg`;
|
|
108
|
+
}
|
|
109
|
+
if (lowerPath.endsWith('.tiff') || lowerPath.endsWith('.tif')) {
|
|
110
|
+
return `${originalPath}.jpg`;
|
|
111
|
+
}
|
|
112
|
+
// JPG, PNG, and other formats return as-is
|
|
113
|
+
return originalPath;
|
|
114
|
+
}
|
|
115
|
+
/**
|
|
116
|
+
* Get the original path from a preview path
|
|
117
|
+
* Handles HEIC.jpg -> HEIC and TIFF.jpg -> TIFF conversions
|
|
118
|
+
*/
|
|
119
|
+
export function getOriginalPath(previewPath) {
|
|
120
|
+
// If it ends with .jpg, check if it's a preview
|
|
121
|
+
if (previewPath.endsWith('.jpg')) {
|
|
122
|
+
const withoutJpg = previewPath.slice(0, -4);
|
|
123
|
+
if (withoutJpg.toLowerCase().endsWith('.heic')) {
|
|
124
|
+
return withoutJpg;
|
|
125
|
+
}
|
|
126
|
+
if (withoutJpg.toLowerCase().endsWith('.tiff') ||
|
|
127
|
+
withoutJpg.toLowerCase().endsWith('.tif')) {
|
|
128
|
+
return withoutJpg;
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
return previewPath;
|
|
132
|
+
}
|
|
133
|
+
/**
|
|
134
|
+
* Extract enrichments of a specific kind from a media message
|
|
135
|
+
*/
|
|
136
|
+
export function getEnrichmentsByKind(message, kind) {
|
|
137
|
+
if (message.messageKind !== 'media' || !message.media?.enrichment) {
|
|
138
|
+
return [];
|
|
139
|
+
}
|
|
140
|
+
return message.media.enrichment.filter((e) => e.kind === kind);
|
|
141
|
+
}
|
|
142
|
+
/**
|
|
143
|
+
* Get all transcription enrichments from a message
|
|
144
|
+
*/
|
|
145
|
+
export function getTranscriptions(message) {
|
|
146
|
+
return getEnrichmentsByKind(message, 'transcription');
|
|
147
|
+
}
|
|
148
|
+
/**
|
|
149
|
+
* Get all link context enrichments from a message
|
|
150
|
+
*/
|
|
151
|
+
export function getLinkContexts(message) {
|
|
152
|
+
return getEnrichmentsByKind(message, 'link_context');
|
|
153
|
+
}
|
|
154
|
+
/**
|
|
155
|
+
* Get all PDF summary enrichments from a message
|
|
156
|
+
*/
|
|
157
|
+
export function getPdfSummaries(message) {
|
|
158
|
+
return getEnrichmentsByKind(message, 'pdf_summary');
|
|
159
|
+
}
|
|
160
|
+
export function renderAllEnrichments(message) {
|
|
161
|
+
const result = {
|
|
162
|
+
embeds: [],
|
|
163
|
+
transcriptions: [],
|
|
164
|
+
linkContexts: [],
|
|
165
|
+
pdfSummaries: [],
|
|
166
|
+
};
|
|
167
|
+
// Handle image embeds
|
|
168
|
+
if (shouldRenderEmbed(message)) {
|
|
169
|
+
const embedPath = getEmbedPath(message);
|
|
170
|
+
if (embedPath) {
|
|
171
|
+
const previewPath = getPreviewPath(embedPath);
|
|
172
|
+
if (previewPath === embedPath) {
|
|
173
|
+
// No preview needed, just embed
|
|
174
|
+
result.embeds.push(renderImageEmbed(embedPath));
|
|
175
|
+
}
|
|
176
|
+
else {
|
|
177
|
+
// Preview available, show with link to original
|
|
178
|
+
result.embeds.push(renderPreviewImageWithLink(previewPath, embedPath));
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
// Handle enrichments if media
|
|
183
|
+
if (message.media?.enrichment) {
|
|
184
|
+
for (const enrichment of message.media.enrichment) {
|
|
185
|
+
if (enrichment.kind === 'transcription') {
|
|
186
|
+
const rendered = renderTranscriptionBlockquote(enrichment);
|
|
187
|
+
if (rendered)
|
|
188
|
+
result.transcriptions.push(rendered);
|
|
189
|
+
}
|
|
190
|
+
else if (enrichment.kind === 'link_context') {
|
|
191
|
+
const rendered = renderLinkContextBlockquote(enrichment);
|
|
192
|
+
if (rendered)
|
|
193
|
+
result.linkContexts.push(rendered);
|
|
194
|
+
}
|
|
195
|
+
else if (enrichment.kind === 'pdf_summary') {
|
|
196
|
+
const rendered = renderPdfSummaryBlockquote(enrichment);
|
|
197
|
+
if (rendered)
|
|
198
|
+
result.pdfSummaries.push(rendered);
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
return result;
|
|
203
|
+
}
|
|
204
|
+
//# sourceMappingURL=embeds-blockquotes.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"embeds-blockquotes.js","sourceRoot":"","sources":["../../src/render/embeds-blockquotes.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Grouping and Anchor Generation Module (RENDER--T01)
|
|
3
|
+
*
|
|
4
|
+
* Implements message grouping and Obsidian-friendly anchor generation:
|
|
5
|
+
* - AC01: Group messages by date (YYYY-MM-DD)
|
|
6
|
+
* - AC02: Sub-group by time-of-day (Morning/Afternoon/Evening)
|
|
7
|
+
* - AC03: Generate unique anchor IDs (#msg-{guid})
|
|
8
|
+
* - AC04: Obsidian-compatible deep-link anchors
|
|
9
|
+
* - AC05: Maintain chronological ordering within time-of-day groups
|
|
10
|
+
*/
|
|
11
|
+
import type { Message } from '#schema/message';
|
|
12
|
+
/**
|
|
13
|
+
* Time-of-day classification
|
|
14
|
+
*/
|
|
15
|
+
export type TimeOfDay = 'morning' | 'afternoon' | 'evening';
|
|
16
|
+
/**
|
|
17
|
+
* Group structure for a single time-of-day period
|
|
18
|
+
*/
|
|
19
|
+
export type TimeOfDayGroup = {
|
|
20
|
+
morning: Message[];
|
|
21
|
+
afternoon: Message[];
|
|
22
|
+
evening: Message[];
|
|
23
|
+
};
|
|
24
|
+
/**
|
|
25
|
+
* Grouped messages by date and time-of-day
|
|
26
|
+
* Key: YYYY-MM-DD
|
|
27
|
+
*/
|
|
28
|
+
export type GroupedMessages = {
|
|
29
|
+
[date: string]: TimeOfDayGroup;
|
|
30
|
+
};
|
|
31
|
+
/**
|
|
32
|
+
* AC02: Classify a timestamp into time-of-day category
|
|
33
|
+
* Morning: 00:00-11:59
|
|
34
|
+
* Afternoon: 12:00-17:59
|
|
35
|
+
* Evening: 18:00-23:59
|
|
36
|
+
*/
|
|
37
|
+
export declare function classifyTimeOfDay(isoTimestamp: string): TimeOfDay;
|
|
38
|
+
/**
|
|
39
|
+
* AC03: Generate unique anchor ID for a message
|
|
40
|
+
* Format: #msg-{guid}
|
|
41
|
+
*/
|
|
42
|
+
export declare function generateAnchorId(guid: string): string;
|
|
43
|
+
/**
|
|
44
|
+
* AC01: Extract date from ISO timestamp in YYYY-MM-DD format
|
|
45
|
+
*/
|
|
46
|
+
export declare function extractDate(isoTimestamp: string): string;
|
|
47
|
+
/**
|
|
48
|
+
* AC05: Sort messages chronologically by timestamp
|
|
49
|
+
* Does not mutate original array
|
|
50
|
+
*/
|
|
51
|
+
export declare function sortByTimestamp(messages: Message[]): Message[];
|
|
52
|
+
/**
|
|
53
|
+
* AC01-AC05: Group messages by date and time-of-day
|
|
54
|
+
* Returns nested structure with chronological ordering maintained
|
|
55
|
+
*/
|
|
56
|
+
export declare function groupMessagesByDateAndTimeOfDay(messages: Message[]): GroupedMessages;
|
|
57
|
+
/**
|
|
58
|
+
* Get all unique dates from grouped messages
|
|
59
|
+
* Returns dates in chronological order
|
|
60
|
+
*/
|
|
61
|
+
export declare function getDatesSorted(grouped: GroupedMessages): string[];
|
|
62
|
+
/**
|
|
63
|
+
* Get all messages from a date group in chronological order
|
|
64
|
+
* Combines all time-of-day groups in order
|
|
65
|
+
*/
|
|
66
|
+
export declare function getAllMessagesForDate(dateGroup: TimeOfDayGroup): Message[];
|
|
67
|
+
/**
|
|
68
|
+
* Type guards and utilities
|
|
69
|
+
*/
|
|
70
|
+
/**
|
|
71
|
+
* Check if date group has any messages
|
|
72
|
+
*/
|
|
73
|
+
export declare function hasMessages(dateGroup: TimeOfDayGroup): boolean;
|
|
74
|
+
/**
|
|
75
|
+
* Get count of messages in time-of-day
|
|
76
|
+
*/
|
|
77
|
+
export declare function getMessageCount(dateGroup: TimeOfDayGroup): number;
|
|
78
|
+
//# sourceMappingURL=grouping.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"grouping.d.ts","sourceRoot":"","sources":["../../src/render/grouping.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,iBAAiB,CAAA;AAc9C;;GAEG;AACH,MAAM,MAAM,SAAS,GAAG,SAAS,GAAG,WAAW,GAAG,SAAS,CAAA;AAE3D;;GAEG;AACH,MAAM,MAAM,cAAc,GAAG;IAC5B,OAAO,EAAE,OAAO,EAAE,CAAA;IAClB,SAAS,EAAE,OAAO,EAAE,CAAA;IACpB,OAAO,EAAE,OAAO,EAAE,CAAA;CAClB,CAAA;AAED;;;GAGG;AACH,MAAM,MAAM,eAAe,GAAG;IAC7B,CAAC,IAAI,EAAE,MAAM,GAAG,cAAc,CAAA;CAC9B,CAAA;AAED;;;;;GAKG;AACH,wBAAgB,iBAAiB,CAAC,YAAY,EAAE,MAAM,GAAG,SAAS,CAWjE;AAED;;;GAGG;AACH,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAErD;AAED;;GAEG;AACH,wBAAgB,WAAW,CAAC,YAAY,EAAE,MAAM,GAAG,MAAM,CAMxD;AAED;;;GAGG;AACH,wBAAgB,eAAe,CAAC,QAAQ,EAAE,OAAO,EAAE,GAAG,OAAO,EAAE,CAM9D;AAED;;;GAGG;AACH,wBAAgB,+BAA+B,CAC9C,QAAQ,EAAE,OAAO,EAAE,GACjB,eAAe,CAgCjB;AAED;;;GAGG;AACH,wBAAgB,cAAc,CAAC,OAAO,EAAE,eAAe,GAAG,MAAM,EAAE,CAIjE;AAED;;;GAGG;AACH,wBAAgB,qBAAqB,CAAC,SAAS,EAAE,cAAc,GAAG,OAAO,EAAE,CAE1E;AAED;;GAEG;AAEH;;GAEG;AACH,wBAAgB,WAAW,CAAC,SAAS,EAAE,cAAc,GAAG,OAAO,CAM9D;AAED;;GAEG;AACH,wBAAgB,eAAe,CAAC,SAAS,EAAE,cAAc,GAAG,MAAM,CAMjE"}
|
|
@@ -0,0 +1,134 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Grouping and Anchor Generation Module (RENDER--T01)
|
|
3
|
+
*
|
|
4
|
+
* Implements message grouping and Obsidian-friendly anchor generation:
|
|
5
|
+
* - AC01: Group messages by date (YYYY-MM-DD)
|
|
6
|
+
* - AC02: Sub-group by time-of-day (Morning/Afternoon/Evening)
|
|
7
|
+
* - AC03: Generate unique anchor IDs (#msg-{guid})
|
|
8
|
+
* - AC04: Obsidian-compatible deep-link anchors
|
|
9
|
+
* - AC05: Maintain chronological ordering within time-of-day groups
|
|
10
|
+
*/
|
|
11
|
+
/**
|
|
12
|
+
* Normalize any ISO-like timestamp to canonical UTC ISO format.
|
|
13
|
+
* - If no timezone designator (no 'Z' and no +/- offset), treat as UTC by appending 'Z'.
|
|
14
|
+
* - Then return Date.toISOString() to canonicalize milliseconds and Z suffix.
|
|
15
|
+
*/
|
|
16
|
+
function normalizeIsoUtc(input) {
|
|
17
|
+
const hasZ = /Z$/.test(input);
|
|
18
|
+
const hasOffset = /[+-]\d{2}:?\d{2}$/.test(input);
|
|
19
|
+
const coerced = hasZ || hasOffset ? input : `${input.replace(/\s+$/, '')}Z`;
|
|
20
|
+
return new Date(coerced).toISOString();
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* AC02: Classify a timestamp into time-of-day category
|
|
24
|
+
* Morning: 00:00-11:59
|
|
25
|
+
* Afternoon: 12:00-17:59
|
|
26
|
+
* Evening: 18:00-23:59
|
|
27
|
+
*/
|
|
28
|
+
export function classifyTimeOfDay(isoTimestamp) {
|
|
29
|
+
const date = new Date(normalizeIsoUtc(isoTimestamp));
|
|
30
|
+
const hours = date.getUTCHours();
|
|
31
|
+
if (hours < 12) {
|
|
32
|
+
return 'morning';
|
|
33
|
+
}
|
|
34
|
+
if (hours < 18) {
|
|
35
|
+
return 'afternoon';
|
|
36
|
+
}
|
|
37
|
+
return 'evening';
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* AC03: Generate unique anchor ID for a message
|
|
41
|
+
* Format: #msg-{guid}
|
|
42
|
+
*/
|
|
43
|
+
export function generateAnchorId(guid) {
|
|
44
|
+
return `#msg-${guid}`;
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* AC01: Extract date from ISO timestamp in YYYY-MM-DD format
|
|
48
|
+
*/
|
|
49
|
+
export function extractDate(isoTimestamp) {
|
|
50
|
+
const date = new Date(normalizeIsoUtc(isoTimestamp));
|
|
51
|
+
const year = date.getUTCFullYear();
|
|
52
|
+
const month = String(date.getUTCMonth() + 1).padStart(2, '0');
|
|
53
|
+
const day = String(date.getUTCDate()).padStart(2, '0');
|
|
54
|
+
return `${year}-${month}-${day}`;
|
|
55
|
+
}
|
|
56
|
+
/**
|
|
57
|
+
* AC05: Sort messages chronologically by timestamp
|
|
58
|
+
* Does not mutate original array
|
|
59
|
+
*/
|
|
60
|
+
export function sortByTimestamp(messages) {
|
|
61
|
+
return [...messages].sort((a, b) => {
|
|
62
|
+
const timeA = new Date(normalizeIsoUtc(a.date)).getTime();
|
|
63
|
+
const timeB = new Date(normalizeIsoUtc(b.date)).getTime();
|
|
64
|
+
return timeA - timeB;
|
|
65
|
+
});
|
|
66
|
+
}
|
|
67
|
+
/**
|
|
68
|
+
* AC01-AC05: Group messages by date and time-of-day
|
|
69
|
+
* Returns nested structure with chronological ordering maintained
|
|
70
|
+
*/
|
|
71
|
+
export function groupMessagesByDateAndTimeOfDay(messages) {
|
|
72
|
+
const grouped = {};
|
|
73
|
+
// First pass: create date groups and classify by time-of-day
|
|
74
|
+
for (const message of messages) {
|
|
75
|
+
const date = extractDate(message.date);
|
|
76
|
+
const timeOfDay = classifyTimeOfDay(message.date);
|
|
77
|
+
// Initialize date group if not exists
|
|
78
|
+
if (!grouped[date]) {
|
|
79
|
+
grouped[date] = {
|
|
80
|
+
morning: [],
|
|
81
|
+
afternoon: [],
|
|
82
|
+
evening: [],
|
|
83
|
+
};
|
|
84
|
+
}
|
|
85
|
+
// Add message to appropriate time-of-day group
|
|
86
|
+
grouped[date][timeOfDay].push(message);
|
|
87
|
+
}
|
|
88
|
+
// Second pass: sort each time-of-day group chronologically
|
|
89
|
+
for (const date in grouped) {
|
|
90
|
+
const dayGroup = grouped[date];
|
|
91
|
+
if (dayGroup) {
|
|
92
|
+
dayGroup.morning = sortByTimestamp(dayGroup.morning);
|
|
93
|
+
dayGroup.afternoon = sortByTimestamp(dayGroup.afternoon);
|
|
94
|
+
dayGroup.evening = sortByTimestamp(dayGroup.evening);
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
return grouped;
|
|
98
|
+
}
|
|
99
|
+
/**
|
|
100
|
+
* Get all unique dates from grouped messages
|
|
101
|
+
* Returns dates in chronological order
|
|
102
|
+
*/
|
|
103
|
+
export function getDatesSorted(grouped) {
|
|
104
|
+
// Keys are YYYY-MM-DD; lexicographic sort is equivalent to chronological
|
|
105
|
+
// Avoid Date parsing entirely to prevent any environment-specific quirks.
|
|
106
|
+
return Object.keys(grouped).sort();
|
|
107
|
+
}
|
|
108
|
+
/**
|
|
109
|
+
* Get all messages from a date group in chronological order
|
|
110
|
+
* Combines all time-of-day groups in order
|
|
111
|
+
*/
|
|
112
|
+
export function getAllMessagesForDate(dateGroup) {
|
|
113
|
+
return [...dateGroup.morning, ...dateGroup.afternoon, ...dateGroup.evening];
|
|
114
|
+
}
|
|
115
|
+
/**
|
|
116
|
+
* Type guards and utilities
|
|
117
|
+
*/
|
|
118
|
+
/**
|
|
119
|
+
* Check if date group has any messages
|
|
120
|
+
*/
|
|
121
|
+
export function hasMessages(dateGroup) {
|
|
122
|
+
return (dateGroup.morning.length > 0 ||
|
|
123
|
+
dateGroup.afternoon.length > 0 ||
|
|
124
|
+
dateGroup.evening.length > 0);
|
|
125
|
+
}
|
|
126
|
+
/**
|
|
127
|
+
* Get count of messages in time-of-day
|
|
128
|
+
*/
|
|
129
|
+
export function getMessageCount(dateGroup) {
|
|
130
|
+
return (dateGroup.morning.length +
|
|
131
|
+
dateGroup.afternoon.length +
|
|
132
|
+
dateGroup.evening.length);
|
|
133
|
+
}
|
|
134
|
+
//# sourceMappingURL=grouping.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"grouping.js","sourceRoot":"","sources":["../../src/render/grouping.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAIH;;;;GAIG;AACH,SAAS,eAAe,CAAC,KAAa;IACrC,MAAM,IAAI,GAAG,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,CAAA;IAC7B,MAAM,SAAS,GAAG,mBAAmB,CAAC,IAAI,CAAC,KAAK,CAAC,CAAA;IACjD,MAAM,OAAO,GAAG,IAAI,IAAI,SAAS,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,GAAG,KAAK,CAAC,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC,GAAG,CAAA;IAC3E,OAAO,IAAI,IAAI,CAAC,OAAO,CAAC,CAAC,WAAW,EAAE,CAAA;AACvC,CAAC;AAwBD;;;;;GAKG;AACH,MAAM,UAAU,iBAAiB,CAAC,YAAoB;IACrD,MAAM,IAAI,GAAG,IAAI,IAAI,CAAC,eAAe,CAAC,YAAY,CAAC,CAAC,CAAA;IACpD,MAAM,KAAK,GAAG,IAAI,CAAC,WAAW,EAAE,CAAA;IAEhC,IAAI,KAAK,GAAG,EAAE,EAAE,CAAC;QAChB,OAAO,SAAS,CAAA;IACjB,CAAC;IACD,IAAI,KAAK,GAAG,EAAE,EAAE,CAAC;QAChB,OAAO,WAAW,CAAA;IACnB,CAAC;IACD,OAAO,SAAS,CAAA;AACjB,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,gBAAgB,CAAC,IAAY;IAC5C,OAAO,QAAQ,IAAI,EAAE,CAAA;AACtB,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,WAAW,CAAC,YAAoB;IAC/C,MAAM,IAAI,GAAG,IAAI,IAAI,CAAC,eAAe,CAAC,YAAY,CAAC,CAAC,CAAA;IACpD,MAAM,IAAI,GAAG,IAAI,CAAC,cAAc,EAAE,CAAA;IAClC,MAAM,KAAK,GAAG,MAAM,CAAC,IAAI,CAAC,WAAW,EAAE,GAAG,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,EAAE,GAAG,CAAC,CAAA;IAC7D,MAAM,GAAG,GAAG,MAAM,CAAC,IAAI,CAAC,UAAU,EAAE,CAAC,CAAC,QAAQ,CAAC,CAAC,EAAE,GAAG,CAAC,CAAA;IACtD,OAAO,GAAG,IAAI,IAAI,KAAK,IAAI,GAAG,EAAE,CAAA;AACjC,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,eAAe,CAAC,QAAmB;IAClD,OAAO,CAAC,GAAG,QAAQ,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE;QAClC,MAAM,KAAK,GAAG,IAAI,IAAI,CAAC,eAAe,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,OAAO,EAAE,CAAA;QACzD,MAAM,KAAK,GAAG,IAAI,IAAI,CAAC,eAAe,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,OAAO,EAAE,CAAA;QACzD,OAAO,KAAK,GAAG,KAAK,CAAA;IACrB,CAAC,CAAC,CAAA;AACH,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,+BAA+B,CAC9C,QAAmB;IAEnB,MAAM,OAAO,GAAoB,EAAE,CAAA;IAEnC,6DAA6D;IAC7D,KAAK,MAAM,OAAO,IAAI,QAAQ,EAAE,CAAC;QAChC,MAAM,IAAI,GAAG,WAAW,CAAC,OAAO,CAAC,IAAI,CAAC,CAAA;QACtC,MAAM,SAAS,GAAG,iBAAiB,CAAC,OAAO,CAAC,IAAI,CAAC,CAAA;QAEjD,sCAAsC;QACtC,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,CAAC;YACpB,OAAO,CAAC,IAAI,CAAC,GAAG;gBACf,OAAO,EAAE,EAAE;gBACX,SAAS,EAAE,EAAE;gBACb,OAAO,EAAE,EAAE;aACX,CAAA;QACF,CAAC;QAED,+CAA+C;QAC/C,OAAO,CAAC,IAAI,CAAC,CAAC,SAAS,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,CAAA;IACvC,CAAC;IAED,2DAA2D;IAC3D,KAAK,MAAM,IAAI,IAAI,OAAO,EAAE,CAAC;QAC5B,MAAM,QAAQ,GAAG,OAAO,CAAC,IAAI,CAAC,CAAA;QAC9B,IAAI,QAAQ,EAAE,CAAC;YACd,QAAQ,CAAC,OAAO,GAAG,eAAe,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAA;YACpD,QAAQ,CAAC,SAAS,GAAG,eAAe,CAAC,QAAQ,CAAC,SAAS,CAAC,CAAA;YACxD,QAAQ,CAAC,OAAO,GAAG,eAAe,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAA;QACrD,CAAC;IACF,CAAC;IAED,OAAO,OAAO,CAAA;AACf,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,cAAc,CAAC,OAAwB;IACtD,yEAAyE;IACzE,0EAA0E;IAC1E,OAAO,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,IAAI,EAAE,CAAA;AACnC,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,qBAAqB,CAAC,SAAyB;IAC9D,OAAO,CAAC,GAAG,SAAS,CAAC,OAAO,EAAE,GAAG,SAAS,CAAC,SAAS,EAAE,GAAG,SAAS,CAAC,OAAO,CAAC,CAAA;AAC5E,CAAC;AAED;;GAEG;AAEH;;GAEG;AACH,MAAM,UAAU,WAAW,CAAC,SAAyB;IACpD,OAAO,CACN,SAAS,CAAC,OAAO,CAAC,MAAM,GAAG,CAAC;QAC5B,SAAS,CAAC,SAAS,CAAC,MAAM,GAAG,CAAC;QAC9B,SAAS,CAAC,OAAO,CAAC,MAAM,GAAG,CAAC,CAC5B,CAAA;AACF,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,eAAe,CAAC,SAAyB;IACxD,OAAO,CACN,SAAS,CAAC,OAAO,CAAC,MAAM;QACxB,SAAS,CAAC,SAAS,CAAC,MAAM;QAC1B,SAAS,CAAC,OAAO,CAAC,MAAM,CACxB,CAAA;AACF,CAAC"}
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Render-Markdown Integration Module (RENDER--T04)
|
|
3
|
+
*
|
|
4
|
+
* Deterministic rendering pipeline:
|
|
5
|
+
* - AC01: Snapshot tests for fixed input → identical output
|
|
6
|
+
* - AC02: No network calls during rendering
|
|
7
|
+
* - AC03: Deterministic ordering of same-timestamp messages
|
|
8
|
+
* - AC04: Reproducible markdown structure
|
|
9
|
+
* - AC05: Performance validation (1000 messages in <10s)
|
|
10
|
+
*/
|
|
11
|
+
import type { Message } from '#schema/message';
|
|
12
|
+
/**
|
|
13
|
+
* Main render function: Convert messages to markdown files
|
|
14
|
+
* Returns Map<date, markdown> with deterministic output
|
|
15
|
+
*/
|
|
16
|
+
export declare function renderMessages(messages: Message[]): Map<string, string>;
|
|
17
|
+
/**
|
|
18
|
+
* Sort messages deterministically by timestamp, then by GUID
|
|
19
|
+
* Ensures same-timestamp messages are ordered consistently
|
|
20
|
+
*/
|
|
21
|
+
export declare function sortMessagesByTimestamp(messages: Message[]): Message[];
|
|
22
|
+
/**
|
|
23
|
+
* Generate deterministic hash of rendered output
|
|
24
|
+
* Uses SHA-256 of concatenated message data
|
|
25
|
+
*/
|
|
26
|
+
export declare function getMessageHash(messages: Message[]): string;
|
|
27
|
+
/**
|
|
28
|
+
* Verify determinism by rendering multiple times and comparing
|
|
29
|
+
*/
|
|
30
|
+
export type DeterminismResult = {
|
|
31
|
+
isDeterministic: boolean;
|
|
32
|
+
runsCount: number;
|
|
33
|
+
hashesAreIdentical: boolean;
|
|
34
|
+
outputsAreIdentical: boolean;
|
|
35
|
+
hashes: string[];
|
|
36
|
+
};
|
|
37
|
+
export declare function verifyDeterminism(messages: Message[], runsCount?: number): DeterminismResult;
|
|
38
|
+
/**
|
|
39
|
+
* Validate markdown structure
|
|
40
|
+
* Ensures proper formatting and no encoding issues
|
|
41
|
+
*/
|
|
42
|
+
export declare function validateMarkdownStructure(markdown: string): void;
|
|
43
|
+
/**
|
|
44
|
+
* Export types for external use
|
|
45
|
+
*/
|
|
46
|
+
export type { Message } from '#schema/message';
|
|
47
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/render/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAGH,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,iBAAiB,CAAA;AAkB9C;;;GAGG;AACH,wBAAgB,cAAc,CAAC,QAAQ,EAAE,OAAO,EAAE,GAAG,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAoCvE;AA4HD;;;GAGG;AACH,wBAAgB,uBAAuB,CAAC,QAAQ,EAAE,OAAO,EAAE,GAAG,OAAO,EAAE,CAYtE;AAED;;;GAGG;AACH,wBAAgB,cAAc,CAAC,QAAQ,EAAE,OAAO,EAAE,GAAG,MAAM,CAK1D;AAED;;GAEG;AACH,MAAM,MAAM,iBAAiB,GAAG;IAC/B,eAAe,EAAE,OAAO,CAAA;IACxB,SAAS,EAAE,MAAM,CAAA;IACjB,kBAAkB,EAAE,OAAO,CAAA;IAC3B,mBAAmB,EAAE,OAAO,CAAA;IAC5B,MAAM,EAAE,MAAM,EAAE,CAAA;CAChB,CAAA;AAED,wBAAgB,iBAAiB,CAChC,QAAQ,EAAE,OAAO,EAAE,EACnB,SAAS,SAAI,GACX,iBAAiB,CA6CnB;AAED;;;GAGG;AACH,wBAAgB,yBAAyB,CAAC,QAAQ,EAAE,MAAM,GAAG,IAAI,CA+BhE;AAED;;GAEG;AACH,YAAY,EAAE,OAAO,EAAE,MAAM,iBAAiB,CAAA"}
|