python-codex 0.3.1__py3-none-any.whl → 0.3.3__py3-none-any.whl

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.
@@ -5,6 +5,7 @@
5
5
  <meta name="viewport" content="width=device-width, initial-scale=1">
6
6
  <title>__WORKSPACE_TITLE__</title>
7
7
  <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/katex@0.16.22/dist/katex.min.css">
8
+ <link rel="stylesheet" href="assets/content_views.css">
8
9
  <style>
9
10
  :root {
10
11
  color-scheme: light;
@@ -78,61 +79,18 @@
78
79
  min-width: 0;
79
80
  border-bottom: 1px solid var(--line);
80
81
  height: 44px;
81
- padding: 0 12px;
82
+ padding: 0 8px;
82
83
  color: var(--muted);
83
84
  font-size: 12px;
84
85
  display: flex;
85
86
  align-items: center;
86
- gap: 10px;
87
+ gap: 8px;
87
88
  white-space: nowrap;
88
89
  overflow: hidden;
89
90
  }
90
- .boardbar-paths {
91
- min-width: 0;
92
- display: flex;
93
- align-items: baseline;
94
- gap: 12px;
95
- overflow: hidden;
96
- line-height: 1.4;
97
- }
98
- .boardbar-title {
99
- color: var(--ink);
100
- font-size: 14px;
101
- font-weight: 600;
102
- }
103
- .boardbar-paths code { border: 0; padding: 0; background: none; font-size: 11px; }
104
- .board-location { margin-left: auto; font-size: 11px; overflow: hidden; text-overflow: ellipsis; }
105
- .boardbar-paths span {
106
- min-width: 0;
107
- overflow: hidden;
108
- text-overflow: ellipsis;
109
- }
110
91
  .workspace-back {
111
- flex: 0 0 auto;
112
- display: inline-flex;
113
- align-items: center;
114
- justify-content: center;
115
- width: 32px;
116
- height: 32px;
117
- border: 0;
118
- border-radius: var(--radius-sm);
119
- background: transparent;
120
- color: var(--ink);
121
- padding: 0;
122
92
  text-decoration: none;
123
93
  }
124
- .workspace-back:hover {
125
- background: var(--accent-soft);
126
- }
127
- .workspace-back:focus {
128
- outline: 2px solid var(--accent);
129
- outline-offset: 1px;
130
- }
131
- .workspace-back svg {
132
- display: block;
133
- width: 18px;
134
- height: 18px;
135
- }
136
94
  .board {
137
95
  border: 0;
138
96
  min-width: 0;
@@ -286,7 +244,10 @@
286
244
  gap: 4px;
287
245
  min-width: 0;
288
246
  overflow-x: auto;
289
- scrollbar-width: thin;
247
+ scrollbar-width: none;
248
+ }
249
+ .tabs::-webkit-scrollbar {
250
+ display: none;
290
251
  }
291
252
  .tab {
292
253
  position: relative;
@@ -309,7 +270,8 @@
309
270
  background: var(--panel-hover);
310
271
  color: var(--ink);
311
272
  }
312
- .tab-new:focus-visible {
273
+ .tab-new:focus-visible,
274
+ .workspace-back:focus-visible {
313
275
  outline: 2px solid var(--accent);
314
276
  outline-offset: 1px;
315
277
  }
@@ -375,7 +337,8 @@
375
337
  user-select: text;
376
338
  }
377
339
  .tab-close,
378
- .tab-new {
340
+ .tab-new,
341
+ .workspace-back {
379
342
  width: 31px;
380
343
  height: 31px;
381
344
  border: 0;
@@ -403,14 +366,16 @@
403
366
  width: 12px;
404
367
  height: 12px;
405
368
  }
406
- .tab-new {
369
+ .tab-new,
370
+ .workspace-back {
407
371
  display: grid;
408
372
  place-items: center;
409
373
  width: 30px;
410
374
  height: 30px;
411
375
  background: var(--panel-deep);
412
376
  }
413
- .tab-new svg {
377
+ .tab-new svg,
378
+ .workspace-back svg {
414
379
  display: block;
415
380
  width: 18px;
416
381
  height: 18px;
@@ -425,7 +390,8 @@
425
390
  cursor: default;
426
391
  }
427
392
  .tab-close:hover,
428
- .tab-new:hover {
393
+ .tab-new:hover,
394
+ .workspace-back:hover {
429
395
  color: var(--ink);
430
396
  background: var(--panel-hover);
431
397
  }
@@ -913,8 +879,6 @@
913
879
  .workspace[data-mobile-pane="chat"] .board-pane,
914
880
  .workspace[data-mobile-pane="board"] .chat { display: none; }
915
881
  .topbar { height: 44px; padding: 6px 16px; }
916
- .boardbar { padding: 0 16px; }
917
- .board-location { display: none; }
918
882
  .log { padding: 14px 16px; gap: 14px; }
919
883
  .composer { padding: 8px 16px max(10px, env(safe-area-inset-bottom)); }
920
884
  textarea { font-size: 16px; line-height: 24px; padding: 2px 0; }
@@ -933,11 +897,9 @@
933
897
  <path d="M15 6l-6 6 6 6"/>
934
898
  </svg>
935
899
  </a>
936
- <div class="boardbar-paths">
937
- <span class="boardbar-title">__WORKSPACE_TITLE__</span>
938
- <span title="__CWD_LABEL__"><code>__CWD_LABEL__</code></span>
939
- </div>
940
- <span class="board-location" title="__BOARD_LABEL__">Board</span>
900
+ <div id="contentTabs" class="tabs content-tabs" role="tablist" aria-label="Board views"
901
+ data-board-title="Workspace: __WORKSPACE_TITLE__&#10;Current dir: __CWD_LABEL__&#10;Canvas file: __BOARD_LABEL__"></div>
902
+ <span id="viewStatus" class="content-status" role="status" hidden></span>
941
903
  <button class="pane-toggle" type="button" data-pane="chat" title="Show chat" aria-label="Show chat">
942
904
  <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5"
943
905
  stroke-linecap="round" stroke-linejoin="round" aria-hidden="true">
@@ -945,7 +907,10 @@
945
907
  </svg>
946
908
  </button>
947
909
  </div>
948
- <iframe id="boardFrame" class="board" src="board" title="board"></iframe>
910
+ <div class="content-area">
911
+ <iframe id="boardFrame" class="board" src="board" title="Canvas"></iframe>
912
+ <div id="contentView" class="content-view" role="tabpanel" hidden></div>
913
+ </div>
949
914
  </section>
950
915
  <button id="splitter" class="splitter" type="button" aria-label="Resize chat panel"></button>
951
916
  <section class="chat" aria-label="pycodex chat">
@@ -1025,7 +990,9 @@
1025
990
  <script src="https://cdn.jsdelivr.net/npm/dompurify@3.2.6/dist/purify.min.js"></script>
1026
991
  <script src="https://cdn.jsdelivr.net/npm/katex@0.16.22/dist/katex.min.js"></script>
1027
992
  <script src="https://cdn.jsdelivr.net/npm/katex@0.16.22/dist/contrib/auto-render.min.js"></script>
1028
- <script>
993
+ <script type="module">
994
+ import {isWorkspaceLink, mountContentViews} from "./assets/content_views.mjs";
995
+
1029
996
  const log = document.getElementById("log");
1030
997
  const spinner = document.getElementById("spinner");
1031
998
  const queueHint = document.getElementById("queueHint");
@@ -1060,6 +1027,18 @@
1060
1027
  const markdownRenderer = window.markdownit
1061
1028
  ? window.markdownit({html: false, linkify: true, breaks: false})
1062
1029
  : null;
1030
+ if (markdownRenderer) {
1031
+ markdownRenderer.renderer.rules.link_open = (tokens, index, options, env, renderer) => {
1032
+ const token = tokens[index];
1033
+ const href = token.attrGet("href");
1034
+ if (isWorkspaceLink(href)) {
1035
+ token.attrSet("data-workspace-link", href);
1036
+ // Preserve file/URI destinations without widening DOMPurify's protocol allowlist.
1037
+ token.attrSet("href", "#");
1038
+ }
1039
+ return renderer.renderToken(tokens, index, options);
1040
+ };
1041
+ }
1063
1042
  const mathDelimiters = [
1064
1043
  {left: "$$", right: "$$", display: true},
1065
1044
  {left: "\\[", right: "\\]", display: true},
@@ -1146,8 +1125,13 @@
1146
1125
  });
1147
1126
  renderProtectedMath(root, protectedMath.expressions);
1148
1127
  root.querySelectorAll("a").forEach((anchor) => {
1149
- anchor.target = "_blank";
1150
- anchor.rel = "noopener noreferrer";
1128
+ const link = anchor.getAttribute("data-workspace-link");
1129
+ if (isWorkspaceLink(link)) {
1130
+ anchor.setAttribute("href", link);
1131
+ } else if (!(anchor.getAttribute("href") || "").startsWith("#")) {
1132
+ anchor.target = "_blank";
1133
+ anchor.rel = "noopener noreferrer";
1134
+ }
1151
1135
  });
1152
1136
  renderMermaidInto(root);
1153
1137
  }
@@ -2206,6 +2190,78 @@
2206
2190
  resizePrompt();
2207
2191
  startPolling();
2208
2192
  startBoardPolling();
2193
+ document.querySelectorAll(".tabs").forEach(tabs => {
2194
+ tabs.addEventListener("wheel", event => {
2195
+ if (event.ctrlKey || event.shiftKey || event.deltaX !== 0 || event.deltaY === 0) return;
2196
+ const previous = tabs.scrollLeft;
2197
+ const unit = event.deltaMode === 1 ? tabs.clientHeight : event.deltaMode === 2 ? tabs.clientWidth : 1;
2198
+ tabs.scrollLeft += event.deltaY * unit;
2199
+ if (tabs.scrollLeft !== previous) event.preventDefault();
2200
+ }, {passive: false});
2201
+ });
2202
+
2203
+ const contentTabs = mountContentViews({
2204
+ tabs: document.getElementById("contentTabs"),
2205
+ frame: document.getElementById("boardFrame"),
2206
+ content: document.getElementById("contentView"),
2207
+ status: document.getElementById("viewStatus"),
2208
+ storage: window.localStorage,
2209
+ storageKey: "pycodex.workspace.contentTab:" + window.location.pathname,
2210
+ renderMarkdown: renderMarkdownInto,
2211
+ request: async (path, options = {}) => {
2212
+ const response = await fetch(new URL(path, window.location.href), options);
2213
+ const payload = await response.json();
2214
+ if (!response.ok) throw new Error(payload.detail || "HTTP " + response.status);
2215
+ return payload;
2216
+ },
2217
+ });
2218
+ let canvasDocument = null;
2219
+
2220
+ function followViewLink(event, href) {
2221
+ if (event.defaultPrevented || event.button !== 0) return;
2222
+ event.preventDefault();
2223
+ contentTabs.open(href).catch(error => showToast("Unable to open view: " + error.message));
2224
+ }
2225
+
2226
+ function followMarkdownLink(event) {
2227
+ const anchor = event.target.closest("a[data-workspace-link]");
2228
+ if (anchor) followViewLink(event, anchor.getAttribute("data-workspace-link"));
2229
+ }
2230
+
2231
+ function followCanvasLink(event) {
2232
+ const anchor = event.target.closest("a[href]");
2233
+ if (anchor && isWorkspaceLink(anchor.getAttribute("href"), false)) {
2234
+ followViewLink(event, anchor.getAttribute("href"));
2235
+ }
2236
+ }
2237
+
2238
+ function bindCanvasLinks() {
2239
+ if (canvasDocument) canvasDocument.removeEventListener("click", followCanvasLink);
2240
+ canvasDocument = boardFrame.contentDocument;
2241
+ if (canvasDocument) canvasDocument.addEventListener("click", followCanvasLink);
2242
+ }
2243
+
2244
+ function startContentViews() {
2245
+ document.addEventListener("click", followMarkdownLink);
2246
+ boardFrame.addEventListener("load", bindCanvasLinks);
2247
+ bindCanvasLinks();
2248
+ contentTabs.start();
2249
+ }
2250
+
2251
+ function stopContentViews() {
2252
+ document.removeEventListener("click", followMarkdownLink);
2253
+ boardFrame.removeEventListener("load", bindCanvasLinks);
2254
+ if (canvasDocument) canvasDocument.removeEventListener("click", followCanvasLink);
2255
+ canvasDocument = null;
2256
+ contentTabs.stop();
2257
+ }
2258
+
2259
+ startContentViews();
2260
+ window.addEventListener("pagehide", stopContentViews);
2261
+ window.addEventListener("pageshow", startContentViews);
2262
+ document.addEventListener("visibilitychange", () => {
2263
+ if (document.visibilityState === "visible") contentTabs.poll();
2264
+ });
2209
2265
  </script>
2210
2266
  </body>
2211
2267
  </html>