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