aeo.js 0.0.3 → 0.0.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/widget.mjs CHANGED
@@ -11,7 +11,7 @@ function getStyles(theme) {
11
11
 
12
12
  .aeo-toggle {
13
13
  position: fixed;
14
- z-index: 10001;
14
+ z-index: 2147483647;
15
15
  font-family: 'JetBrains Mono', monospace;
16
16
  font-size: 14px;
17
17
  animation: aeo-fade-in 0.3s ease;
@@ -85,12 +85,15 @@ function getStyles(theme) {
85
85
  left: 0;
86
86
  right: 0;
87
87
  bottom: 0;
88
+ width: 100vw;
89
+ height: 100vh;
88
90
  background: ${t.background};
89
- z-index: 10000;
91
+ z-index: 2147483646;
90
92
  display: flex;
91
93
  flex-direction: column;
92
94
  animation: aeo-fade-in 0.2s ease;
93
95
  font-family: 'JetBrains Mono', monospace;
96
+ isolation: isolate;
94
97
  }
95
98
 
96
99
  /* Top bar */
@@ -213,6 +216,177 @@ function getStyles(theme) {
213
216
  stroke: currentColor;
214
217
  }
215
218
 
219
+ /* View tabs */
220
+ .aeo-view-tabs {
221
+ display: flex;
222
+ gap: 2px;
223
+ background: rgba(255, 255, 255, 0.05);
224
+ border-radius: 8px;
225
+ padding: 2px;
226
+ border: 1px solid rgba(255, 255, 255, 0.08);
227
+ }
228
+
229
+ .aeo-view-tab {
230
+ padding: 5px 12px;
231
+ background: transparent;
232
+ color: ${t.text};
233
+ border: none;
234
+ border-radius: 6px;
235
+ font-family: inherit;
236
+ font-size: 12px;
237
+ font-weight: 500;
238
+ cursor: pointer;
239
+ transition: all 0.15s ease;
240
+ }
241
+
242
+ .aeo-view-tab:hover {
243
+ background: rgba(255, 255, 255, 0.05);
244
+ }
245
+
246
+ .aeo-view-tab.aeo-view-active {
247
+ background: rgba(255, 255, 255, 0.1);
248
+ color: ${t.accent};
249
+ }
250
+
251
+ /* Metadata bar */
252
+ .aeo-meta-bar {
253
+ display: flex;
254
+ flex-wrap: wrap;
255
+ align-items: center;
256
+ gap: 16px;
257
+ padding: 12px 16px;
258
+ margin-bottom: 24px;
259
+ background: rgba(255, 255, 255, 0.03);
260
+ border: 1px solid rgba(255, 255, 255, 0.06);
261
+ border-radius: 8px;
262
+ font-size: 12px;
263
+ color: ${t.text};
264
+ }
265
+
266
+ .aeo-meta-label {
267
+ color: rgba(160, 160, 168, 0.5);
268
+ margin-right: 4px;
269
+ }
270
+
271
+ .aeo-meta-sep {
272
+ width: 1px;
273
+ height: 14px;
274
+ background: rgba(255, 255, 255, 0.1);
275
+ }
276
+
277
+ /* Rendered markdown view */
278
+ .aeo-rendered {
279
+ color: ${t.text};
280
+ line-height: 1.75;
281
+ font-size: 14px;
282
+ font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
283
+ }
284
+
285
+ .aeo-rendered .aeo-r-h1 {
286
+ font-size: 28px;
287
+ font-weight: 700;
288
+ color: ${t.accent};
289
+ margin: 0 0 16px;
290
+ padding-bottom: 12px;
291
+ border-bottom: 1px solid rgba(255, 255, 255, 0.08);
292
+ line-height: 1.3;
293
+ }
294
+
295
+ .aeo-rendered .aeo-r-h2 {
296
+ font-size: 22px;
297
+ font-weight: 600;
298
+ color: ${t.accent};
299
+ margin: 32px 0 12px;
300
+ line-height: 1.3;
301
+ }
302
+
303
+ .aeo-rendered .aeo-r-h3 {
304
+ font-size: 18px;
305
+ font-weight: 600;
306
+ color: ${t.accent};
307
+ margin: 24px 0 8px;
308
+ line-height: 1.4;
309
+ }
310
+
311
+ .aeo-rendered .aeo-r-h4,
312
+ .aeo-rendered .aeo-r-h5,
313
+ .aeo-rendered .aeo-r-h6 {
314
+ font-size: 15px;
315
+ font-weight: 600;
316
+ color: ${t.accent};
317
+ margin: 20px 0 8px;
318
+ }
319
+
320
+ .aeo-rendered .aeo-r-p {
321
+ margin: 0 0 12px;
322
+ }
323
+
324
+ .aeo-rendered .aeo-r-list {
325
+ margin: 0 0 16px;
326
+ padding-left: 24px;
327
+ }
328
+
329
+ .aeo-rendered .aeo-r-list li {
330
+ margin: 4px 0;
331
+ }
332
+
333
+ .aeo-rendered .aeo-r-quote {
334
+ margin: 16px 0;
335
+ padding: 12px 20px;
336
+ border-left: 3px solid ${t.badge};
337
+ background: rgba(255, 255, 255, 0.02);
338
+ color: ${t.text};
339
+ font-style: italic;
340
+ }
341
+
342
+ .aeo-rendered .aeo-r-hr {
343
+ border: none;
344
+ border-top: 1px solid rgba(255, 255, 255, 0.08);
345
+ margin: 24px 0;
346
+ }
347
+
348
+ .aeo-rendered .aeo-r-code {
349
+ background: rgba(255, 255, 255, 0.05);
350
+ border: 1px solid rgba(255, 255, 255, 0.08);
351
+ border-radius: 8px;
352
+ padding: 16px;
353
+ margin: 16px 0;
354
+ font-family: 'JetBrains Mono', monospace;
355
+ font-size: 13px;
356
+ overflow-x: auto;
357
+ color: ${t.badge};
358
+ }
359
+
360
+ .aeo-rendered .aeo-r-inline-code {
361
+ background: rgba(255, 255, 255, 0.06);
362
+ padding: 2px 6px;
363
+ border-radius: 4px;
364
+ font-family: 'JetBrains Mono', monospace;
365
+ font-size: 0.9em;
366
+ color: ${t.badge};
367
+ }
368
+
369
+ .aeo-rendered .aeo-r-link {
370
+ color: ${t.badge};
371
+ text-decoration: none;
372
+ border-bottom: 1px solid rgba(74, 222, 128, 0.3);
373
+ transition: border-color 0.15s ease;
374
+ }
375
+
376
+ .aeo-rendered .aeo-r-link:hover {
377
+ border-color: ${t.badge};
378
+ }
379
+
380
+ .aeo-rendered strong {
381
+ color: ${t.accent};
382
+ font-weight: 600;
383
+ }
384
+
385
+ .aeo-rendered em {
386
+ font-style: italic;
387
+ opacity: 0.9;
388
+ }
389
+
216
390
  /* Content area */
217
391
  .aeo-content-area {
218
392
  flex: 1;
@@ -355,7 +529,7 @@ function getStyles(theme) {
355
529
  font-size: 13px;
356
530
  opacity: 0;
357
531
  transition: all 0.3s ease;
358
- z-index: 10002;
532
+ z-index: 2147483647;
359
533
  }
360
534
 
361
535
  .aeo-toast.aeo-toast-show {
@@ -404,6 +578,17 @@ function getStyles(theme) {
404
578
  display: none;
405
579
  }
406
580
 
581
+ .aeo-view-tabs {
582
+ order: 10;
583
+ width: 100%;
584
+ justify-content: center;
585
+ }
586
+
587
+ .aeo-meta-bar {
588
+ font-size: 11px;
589
+ gap: 8px;
590
+ }
591
+
407
592
  .aeo-content-area {
408
593
  padding: 24px 16px;
409
594
  }
@@ -813,6 +998,10 @@ var AeoWidget = class {
813
998
  <div class="aeo-topbar">
814
999
  ${((_a = this.config.widget) == null ? void 0 : _a.showBadge) !== false ? '<span class="aeo-badge"><span class="aeo-badge-dot"></span>LLM-READY</span>' : ""}
815
1000
  <span class="aeo-route-tab">${mdPath}</span>
1001
+ <div class="aeo-view-tabs">
1002
+ <button class="aeo-view-tab aeo-view-active" data-view="rendered">Rendered</button>
1003
+ <button class="aeo-view-tab" data-view="source">Source</button>
1004
+ </div>
816
1005
  <div class="aeo-topbar-spacer"></div>
817
1006
  <div class="aeo-topbar-actions">
818
1007
  <button class="aeo-topbar-btn aeo-copy-btn" disabled>
@@ -841,8 +1030,135 @@ var AeoWidget = class {
841
1030
  this.container.appendChild(this.overlayElement);
842
1031
  const closeBtn = this.overlayElement.querySelector(".aeo-close-btn");
843
1032
  closeBtn == null ? void 0 : closeBtn.addEventListener("click", () => this.closeOverlay());
1033
+ const viewTabs = this.overlayElement.querySelectorAll(".aeo-view-tab");
1034
+ viewTabs.forEach((tab) => {
1035
+ tab.addEventListener("click", () => {
1036
+ var _a2, _b;
1037
+ viewTabs.forEach((t) => t.classList.remove("aeo-view-active"));
1038
+ tab.classList.add("aeo-view-active");
1039
+ const view = tab.dataset.view;
1040
+ const rendered = (_a2 = this.overlayElement) == null ? void 0 : _a2.querySelector(".aeo-rendered");
1041
+ const source = (_b = this.overlayElement) == null ? void 0 : _b.querySelector(".aeo-markdown-source");
1042
+ if (rendered && source) {
1043
+ rendered.style.display = view === "rendered" ? "block" : "none";
1044
+ source.style.display = view === "source" ? "block" : "none";
1045
+ }
1046
+ });
1047
+ });
844
1048
  await this.loadContent();
845
1049
  }
1050
+ /**
1051
+ * Strip YAML frontmatter from markdown content.
1052
+ */
1053
+ stripFrontmatter(md) {
1054
+ const frontmatter = {};
1055
+ let body = md;
1056
+ if (md.startsWith("---")) {
1057
+ const endIndex = md.indexOf("---", 3);
1058
+ if (endIndex !== -1) {
1059
+ const fmBlock = md.slice(3, endIndex).trim();
1060
+ body = md.slice(endIndex + 3).trim();
1061
+ for (const line of fmBlock.split("\n")) {
1062
+ const colonIdx = line.indexOf(":");
1063
+ if (colonIdx > 0) {
1064
+ const key = line.slice(0, colonIdx).trim();
1065
+ const val = line.slice(colonIdx + 1).trim().replace(/^["']|["']$/g, "");
1066
+ frontmatter[key] = val;
1067
+ }
1068
+ }
1069
+ }
1070
+ }
1071
+ return { frontmatter, body };
1072
+ }
1073
+ /**
1074
+ * Convert markdown to simple rendered HTML for the "Rendered" view.
1075
+ */
1076
+ renderMarkdown(md) {
1077
+ const esc = (s) => s.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;");
1078
+ const lines = md.split("\n");
1079
+ const html = [];
1080
+ let inList = false;
1081
+ let inCode = false;
1082
+ let codeContent = [];
1083
+ for (const line of lines) {
1084
+ const trimmed = line.trim();
1085
+ if (trimmed.startsWith("```")) {
1086
+ if (inCode) {
1087
+ html.push(`<pre class="aeo-r-code"><code>${esc(codeContent.join("\n"))}</code></pre>`);
1088
+ codeContent = [];
1089
+ inCode = false;
1090
+ } else {
1091
+ if (inList) {
1092
+ html.push("</ul>");
1093
+ inList = false;
1094
+ }
1095
+ inCode = true;
1096
+ }
1097
+ continue;
1098
+ }
1099
+ if (inCode) {
1100
+ codeContent.push(line);
1101
+ continue;
1102
+ }
1103
+ if (!trimmed) {
1104
+ if (inList) {
1105
+ html.push("</ul>");
1106
+ inList = false;
1107
+ }
1108
+ continue;
1109
+ }
1110
+ const headingMatch = trimmed.match(/^(#{1,6})\s+(.*)/);
1111
+ if (headingMatch) {
1112
+ if (inList) {
1113
+ html.push("</ul>");
1114
+ inList = false;
1115
+ }
1116
+ const level = headingMatch[1].length;
1117
+ html.push(`<h${level} class="aeo-r-h${level}">${this.renderInlineMarkdown(esc(headingMatch[2]))}</h${level}>`);
1118
+ continue;
1119
+ }
1120
+ if (/^(-{3,}|\*{3,}|_{3,})$/.test(trimmed)) {
1121
+ if (inList) {
1122
+ html.push("</ul>");
1123
+ inList = false;
1124
+ }
1125
+ html.push('<hr class="aeo-r-hr">');
1126
+ continue;
1127
+ }
1128
+ if (trimmed.startsWith(">")) {
1129
+ if (inList) {
1130
+ html.push("</ul>");
1131
+ inList = false;
1132
+ }
1133
+ html.push(`<blockquote class="aeo-r-quote">${this.renderInlineMarkdown(esc(trimmed.slice(1).trim()))}</blockquote>`);
1134
+ continue;
1135
+ }
1136
+ const listMatch = trimmed.match(/^[-*+]\s+(.*)/);
1137
+ if (listMatch) {
1138
+ if (!inList) {
1139
+ html.push('<ul class="aeo-r-list">');
1140
+ inList = true;
1141
+ }
1142
+ html.push(`<li>${this.renderInlineMarkdown(esc(listMatch[1]))}</li>`);
1143
+ continue;
1144
+ }
1145
+ if (inList) {
1146
+ html.push("</ul>");
1147
+ inList = false;
1148
+ }
1149
+ html.push(`<p class="aeo-r-p">${this.renderInlineMarkdown(esc(trimmed))}</p>`);
1150
+ }
1151
+ if (inList) html.push("</ul>");
1152
+ if (inCode) html.push(`<pre class="aeo-r-code"><code>${esc(codeContent.join("\n"))}</code></pre>`);
1153
+ return html.join("\n");
1154
+ }
1155
+ renderInlineMarkdown(text) {
1156
+ let out = text.replace(/\*\*(.+?)\*\*/g, "<strong>$1</strong>");
1157
+ out = out.replace(/(?<!\*)\*(?!\*)(.+?)(?<!\*)\*(?!\*)/g, "<em>$1</em>");
1158
+ out = out.replace(/`([^`]+)`/g, '<code class="aeo-r-inline-code">$1</code>');
1159
+ out = out.replace(/\[([^\]]+)\]\(([^)]+)\)/g, '<a class="aeo-r-link" href="$2" target="_blank" rel="noopener">$1</a>');
1160
+ return out;
1161
+ }
846
1162
  async loadContent() {
847
1163
  if (!this.overlayElement) return;
848
1164
  const wrapper = this.overlayElement.querySelector(".aeo-content-wrapper");
@@ -856,8 +1172,15 @@ var AeoWidget = class {
856
1172
  } else {
857
1173
  content = extractDOMToMarkdown();
858
1174
  }
1175
+ const { frontmatter, body } = this.stripFrontmatter(content);
1176
+ const metaItems = [];
1177
+ if (frontmatter.title) metaItems.push(`<span class="aeo-meta-label">Title:</span> ${this.escHtml(frontmatter.title)}`);
1178
+ if (frontmatter.url) metaItems.push(`<span class="aeo-meta-label">URL:</span> <a class="aeo-r-link" href="${this.escHtml(frontmatter.url)}" target="_blank">${this.escHtml(frontmatter.url)}</a>`);
1179
+ const metaBar = metaItems.length > 0 ? `<div class="aeo-meta-bar">${metaItems.join('<span class="aeo-meta-sep"></span>')}</div>` : "";
859
1180
  wrapper.innerHTML = `
860
- <pre class="aeo-markdown-source"><code>${this.highlightMarkdown(content)}</code></pre>
1181
+ ${metaBar}
1182
+ <div class="aeo-rendered">${this.renderMarkdown(body)}</div>
1183
+ <pre class="aeo-markdown-source" style="display:none"><code>${this.highlightMarkdown(content)}</code></pre>
861
1184
  `;
862
1185
  const copyBtn = this.overlayElement.querySelector(".aeo-copy-btn");
863
1186
  const downloadBtn = this.overlayElement.querySelector(".aeo-download-btn");
@@ -882,6 +1205,9 @@ var AeoWidget = class {
882
1205
  `;
883
1206
  }
884
1207
  }
1208
+ escHtml(s) {
1209
+ return s.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;").replace(/"/g, "&quot;");
1210
+ }
885
1211
  highlightMarkdown(md) {
886
1212
  var _a;
887
1213
  const esc = (s) => s.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;");