python-codex 0.2.5__py3-none-any.whl → 0.2.6__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.
- {python_codex-0.2.5.dist-info → python_codex-0.2.6.dist-info}/METADATA +19 -3
- {python_codex-0.2.5.dist-info → python_codex-0.2.6.dist-info}/RECORD +6 -6
- workspace_server/workspace.html +293 -99
- {python_codex-0.2.5.dist-info → python_codex-0.2.6.dist-info}/WHEEL +0 -0
- {python_codex-0.2.5.dist-info → python_codex-0.2.6.dist-info}/entry_points.txt +0 -0
- {python_codex-0.2.5.dist-info → python_codex-0.2.6.dist-info}/licenses/LICENSE +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: python-codex
|
|
3
|
-
Version: 0.2.
|
|
3
|
+
Version: 0.2.6
|
|
4
4
|
Summary: A minimal Python extraction of Codex's main agent loop
|
|
5
5
|
License-File: LICENSE
|
|
6
6
|
Requires-Python: >=3.6.2
|
|
@@ -23,8 +23,17 @@ Description-Content-Type: text/markdown
|
|
|
23
23
|
|
|
24
24
|
English README. Chinese version: `README_ZH.md`
|
|
25
25
|
|
|
26
|
-
PyPI
|
|
27
|
-
|
|
26
|
+
PyPI distributions:
|
|
27
|
+
|
|
28
|
+
- Primary package: `python-codex`
|
|
29
|
+
- Workspace install alias: `pycodex-ws`
|
|
30
|
+
|
|
31
|
+
The import path remains `pycodex`; the CLI commands are `pycodex` and
|
|
32
|
+
`pycodex-ws`.
|
|
33
|
+
|
|
34
|
+
`pycodex-ws` is a thin metapackage that depends on the exact matching
|
|
35
|
+
`python-codex` version. The implementation and console script remain owned by
|
|
36
|
+
`python-codex`, so the two distributions never install duplicate modules.
|
|
28
37
|
|
|
29
38
|
This repository extracts the core Codex agent loop from upstream Codex
|
|
30
39
|
(`https://github.com/openai/codex`) into a deliberately small Python version,
|
|
@@ -44,6 +53,13 @@ Relevant Rust reference points:
|
|
|
44
53
|
|
|
45
54
|
## Quick Start
|
|
46
55
|
|
|
56
|
+
Install the full package or the workspace-oriented alias:
|
|
57
|
+
|
|
58
|
+
```bash
|
|
59
|
+
pip install python-codex
|
|
60
|
+
pip install pycodex-ws
|
|
61
|
+
```
|
|
62
|
+
|
|
47
63
|
Install dependencies first:
|
|
48
64
|
|
|
49
65
|
```bash
|
|
@@ -81,11 +81,11 @@ responses_server/tools/web_search.py,sha256=pm4ZUiHUfxc0bGY1kEvt-BCzDrZIyP24xzPU
|
|
|
81
81
|
workspace_server/__init__.py,sha256=PRM4ONODb6hxjBUHkBD4TprE_pkTCIlT9sfftK5ic6M,866
|
|
82
82
|
workspace_server/__main__.py,sha256=9SRp-Yw7ShGxc6DhSIXcDLKgGEdAVm3oBZ59rBOPjT0,62
|
|
83
83
|
workspace_server/app.py,sha256=20lTENFBlercCzFmtAR4fIeMvqIZr8Gq_J2VotmNPck,56858
|
|
84
|
-
workspace_server/workspace.html,sha256=
|
|
84
|
+
workspace_server/workspace.html,sha256=UqUqOfQFra7KV8btI4BUTB38jkkhYZvzzdN5OWpQwdQ,48521
|
|
85
85
|
workspace_server/workspaces.html,sha256=GuYlFiOm1RJINrCKncClHt24D5i7XNABiP9C0xGxBA0,15679
|
|
86
86
|
workspace_server/workspaces.py,sha256=Z-zoj0xgkOOP2CwbQl3vAI6TwLIDUInJKyobs0Jt3ps,19962
|
|
87
|
-
python_codex-0.2.
|
|
88
|
-
python_codex-0.2.
|
|
89
|
-
python_codex-0.2.
|
|
90
|
-
python_codex-0.2.
|
|
91
|
-
python_codex-0.2.
|
|
87
|
+
python_codex-0.2.6.dist-info/METADATA,sha256=AjjNd0oWIKS2og9c2chID0_K4Jz2ICk2z6JfE_npUoM,19288
|
|
88
|
+
python_codex-0.2.6.dist-info/WHEEL,sha256=KGYbc1zXlYddvwxnNty23BeaKzh7YuoSIvIMO4jEhvw,87
|
|
89
|
+
python_codex-0.2.6.dist-info/entry_points.txt,sha256=vkV2UWCtEKvQNMJuPNjt8HyBKiwp83JyqBatrBNGDp8,80
|
|
90
|
+
python_codex-0.2.6.dist-info/licenses/LICENSE,sha256=0X8ifk312hYAORM4hlzg8wVSEXYKNmiPgWlB1YIy2Nw,10926
|
|
91
|
+
python_codex-0.2.6.dist-info/RECORD,,
|
workspace_server/workspace.html
CHANGED
|
@@ -8,22 +8,33 @@
|
|
|
8
8
|
<style>
|
|
9
9
|
:root {
|
|
10
10
|
color-scheme: light;
|
|
11
|
-
--bg: #
|
|
12
|
-
--panel: #
|
|
13
|
-
--
|
|
14
|
-
--
|
|
15
|
-
--
|
|
16
|
-
--
|
|
11
|
+
--bg: #eef3f6;
|
|
12
|
+
--panel: #f8fbfd;
|
|
13
|
+
--panel-deep: #f2f6f8;
|
|
14
|
+
--panel-raised: #ffffff;
|
|
15
|
+
--panel-hover: #e8f1f5;
|
|
16
|
+
--board-chrome: #ffffff;
|
|
17
|
+
--ink: #172630;
|
|
18
|
+
--muted: #60727d;
|
|
19
|
+
--line: #cbd8df;
|
|
20
|
+
--line-strong: #aebfc9;
|
|
21
|
+
--accent: #087f9a;
|
|
17
22
|
--accent-ink: #ffffff;
|
|
18
|
-
--
|
|
19
|
-
--
|
|
20
|
-
--
|
|
21
|
-
--
|
|
22
|
-
--
|
|
23
|
-
--
|
|
24
|
-
--
|
|
25
|
-
--
|
|
26
|
-
--
|
|
23
|
+
--accent-soft: #e6f6f8;
|
|
24
|
+
--warn: #b77908;
|
|
25
|
+
--warn-ink: #62480c;
|
|
26
|
+
--warn-soft: #fff7df;
|
|
27
|
+
--info: #2868b2;
|
|
28
|
+
--info-soft: #edf5ff;
|
|
29
|
+
--success: #247a52;
|
|
30
|
+
--success-line: #8bc9a8;
|
|
31
|
+
--success-soft: #edf9f2;
|
|
32
|
+
--danger: #b33d50;
|
|
33
|
+
--danger-soft: #fff0f2;
|
|
34
|
+
--violet: #6850a4;
|
|
35
|
+
--violet-soft: #f4f0ff;
|
|
36
|
+
--code: #f1f5f7;
|
|
37
|
+
--entry-shadow: 0 1px 2px rgba(27, 57, 72, 0.06);
|
|
27
38
|
--space-1: 2px;
|
|
28
39
|
--space-2: 4px;
|
|
29
40
|
--space-3: 6px;
|
|
@@ -52,14 +63,14 @@
|
|
|
52
63
|
min-width: 0;
|
|
53
64
|
}
|
|
54
65
|
.workspace.collapsed .splitter::after {
|
|
55
|
-
background:
|
|
66
|
+
background: var(--accent);
|
|
56
67
|
}
|
|
57
68
|
.board-pane {
|
|
58
69
|
min-width: 0;
|
|
59
70
|
height: 100dvh;
|
|
60
71
|
display: grid;
|
|
61
72
|
grid-template-rows: auto minmax(0, 1fr);
|
|
62
|
-
background:
|
|
73
|
+
background: var(--board-chrome);
|
|
63
74
|
}
|
|
64
75
|
.boardbar {
|
|
65
76
|
min-width: 0;
|
|
@@ -101,10 +112,10 @@
|
|
|
101
112
|
text-decoration: none;
|
|
102
113
|
}
|
|
103
114
|
.workspace-back:hover {
|
|
104
|
-
background:
|
|
115
|
+
background: var(--accent-soft);
|
|
105
116
|
}
|
|
106
117
|
.workspace-back:focus {
|
|
107
|
-
outline: 2px solid
|
|
118
|
+
outline: 2px solid var(--accent);
|
|
108
119
|
outline-offset: 1px;
|
|
109
120
|
}
|
|
110
121
|
.workspace-back::before {
|
|
@@ -120,16 +131,16 @@
|
|
|
120
131
|
min-width: 0;
|
|
121
132
|
width: 100%;
|
|
122
133
|
height: 100%;
|
|
123
|
-
background:
|
|
134
|
+
background: var(--board-chrome);
|
|
124
135
|
}
|
|
125
136
|
.splitter {
|
|
126
137
|
position: relative;
|
|
127
138
|
width: 8px;
|
|
128
139
|
height: 100dvh;
|
|
129
140
|
border: 0;
|
|
130
|
-
border-left: 1px solid
|
|
131
|
-
border-right: 1px solid
|
|
132
|
-
background:
|
|
141
|
+
border-left: 1px solid var(--line);
|
|
142
|
+
border-right: 1px solid var(--line);
|
|
143
|
+
background: var(--panel-hover);
|
|
133
144
|
cursor: col-resize;
|
|
134
145
|
padding: 0;
|
|
135
146
|
touch-action: none;
|
|
@@ -142,17 +153,17 @@
|
|
|
142
153
|
width: 3px;
|
|
143
154
|
height: 42px;
|
|
144
155
|
border-radius: 999px;
|
|
145
|
-
background:
|
|
156
|
+
background: var(--muted);
|
|
146
157
|
transform: translate(-50%, -50%);
|
|
147
158
|
}
|
|
148
159
|
.splitter:hover,
|
|
149
160
|
.workspace.resizing .splitter {
|
|
150
|
-
background: #
|
|
151
|
-
border-color:
|
|
161
|
+
background: #dce9ee;
|
|
162
|
+
border-color: var(--line-strong);
|
|
152
163
|
}
|
|
153
164
|
.splitter:hover::after,
|
|
154
165
|
.workspace.resizing .splitter::after {
|
|
155
|
-
background:
|
|
166
|
+
background: var(--accent);
|
|
156
167
|
}
|
|
157
168
|
.workspace.resizing,
|
|
158
169
|
.workspace.resizing * {
|
|
@@ -190,8 +201,8 @@
|
|
|
190
201
|
width: var(--context-meter-size);
|
|
191
202
|
height: var(--context-meter-size);
|
|
192
203
|
border-radius: 999px;
|
|
193
|
-
background: conic-gradient(
|
|
194
|
-
color:
|
|
204
|
+
background: conic-gradient(var(--accent) 0 var(--context-remaining), var(--line-strong) 0 100%);
|
|
205
|
+
color: var(--muted);
|
|
195
206
|
font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
|
|
196
207
|
font-size: 9px;
|
|
197
208
|
line-height: 1;
|
|
@@ -205,7 +216,7 @@
|
|
|
205
216
|
position: absolute;
|
|
206
217
|
inset: 4px;
|
|
207
218
|
border-radius: 999px;
|
|
208
|
-
background:
|
|
219
|
+
background: var(--panel);
|
|
209
220
|
}
|
|
210
221
|
.context-meter-value {
|
|
211
222
|
position: relative;
|
|
@@ -227,9 +238,9 @@
|
|
|
227
238
|
min-width: 88px;
|
|
228
239
|
max-width: 180px;
|
|
229
240
|
height: 31px;
|
|
230
|
-
border: 1px solid
|
|
241
|
+
border: 1px solid var(--line);
|
|
231
242
|
border-radius: var(--radius-sm);
|
|
232
|
-
background:
|
|
243
|
+
background: var(--panel-raised);
|
|
233
244
|
color: var(--ink);
|
|
234
245
|
padding: 0 var(--space-3) 0 var(--space-4);
|
|
235
246
|
font: inherit;
|
|
@@ -238,12 +249,12 @@
|
|
|
238
249
|
}
|
|
239
250
|
.tab:focus-within,
|
|
240
251
|
.tab-new:focus {
|
|
241
|
-
outline: 2px solid
|
|
252
|
+
outline: 2px solid var(--accent);
|
|
242
253
|
outline-offset: 1px;
|
|
243
254
|
}
|
|
244
255
|
.tab.active {
|
|
245
|
-
border-color:
|
|
246
|
-
background:
|
|
256
|
+
border-color: var(--accent);
|
|
257
|
+
background: var(--accent-soft);
|
|
247
258
|
box-shadow: inset 0 -2px 0 var(--accent);
|
|
248
259
|
}
|
|
249
260
|
.tab-status {
|
|
@@ -281,7 +292,7 @@
|
|
|
281
292
|
height: 31px;
|
|
282
293
|
border: 1px solid var(--line);
|
|
283
294
|
border-radius: var(--radius-md);
|
|
284
|
-
background:
|
|
295
|
+
background: var(--panel-raised);
|
|
285
296
|
color: var(--muted);
|
|
286
297
|
padding: 0;
|
|
287
298
|
line-height: 1;
|
|
@@ -315,7 +326,7 @@
|
|
|
315
326
|
.tab-close:hover,
|
|
316
327
|
.tab-new:hover {
|
|
317
328
|
color: var(--ink);
|
|
318
|
-
background:
|
|
329
|
+
background: var(--panel-hover);
|
|
319
330
|
}
|
|
320
331
|
.log {
|
|
321
332
|
min-height: 0;
|
|
@@ -325,45 +336,45 @@
|
|
|
325
336
|
display: flex;
|
|
326
337
|
flex-direction: column;
|
|
327
338
|
gap: var(--space-4);
|
|
328
|
-
background:
|
|
339
|
+
background: var(--bg);
|
|
329
340
|
}
|
|
330
341
|
.entry {
|
|
331
342
|
min-width: 0;
|
|
332
343
|
border: 1px solid var(--line);
|
|
333
344
|
border-radius: var(--radius-sm);
|
|
334
345
|
padding: var(--space-4) var(--space-5);
|
|
335
|
-
background:
|
|
346
|
+
background: var(--panel-raised);
|
|
336
347
|
box-shadow: var(--entry-shadow);
|
|
337
348
|
}
|
|
338
349
|
.entry.user {
|
|
339
|
-
border-color:
|
|
350
|
+
border-color: var(--warn);
|
|
340
351
|
background: var(--warn-soft);
|
|
341
|
-
color:
|
|
352
|
+
color: var(--warn-ink);
|
|
342
353
|
}
|
|
343
354
|
.entry.response,
|
|
344
355
|
.entry.assistant {
|
|
345
|
-
border-color:
|
|
346
|
-
background:
|
|
356
|
+
border-color: var(--line);
|
|
357
|
+
background: var(--panel-raised);
|
|
347
358
|
}
|
|
348
359
|
.entry.thinking {
|
|
349
|
-
border-color:
|
|
350
|
-
background:
|
|
351
|
-
color:
|
|
360
|
+
border-color: var(--success-line);
|
|
361
|
+
background: var(--success-soft);
|
|
362
|
+
color: var(--success);
|
|
352
363
|
animation: thinking-breathe 4.8s ease-in-out infinite;
|
|
353
364
|
}
|
|
354
365
|
.entry.control {
|
|
355
|
-
border-color: #
|
|
366
|
+
border-color: #b7d3ee;
|
|
356
367
|
background: var(--info-soft);
|
|
357
368
|
color: var(--info);
|
|
358
369
|
}
|
|
359
370
|
.entry.tool {
|
|
360
|
-
border-color: #
|
|
371
|
+
border-color: #d8cdf1;
|
|
361
372
|
background: var(--violet-soft);
|
|
362
373
|
color: var(--violet);
|
|
363
374
|
font-size: 12px;
|
|
364
375
|
}
|
|
365
376
|
.entry.error {
|
|
366
|
-
border-color: #
|
|
377
|
+
border-color: #efb8c1;
|
|
367
378
|
background: var(--danger-soft);
|
|
368
379
|
color: var(--danger);
|
|
369
380
|
}
|
|
@@ -422,11 +433,11 @@
|
|
|
422
433
|
vertical-align: top;
|
|
423
434
|
}
|
|
424
435
|
.markdown th {
|
|
425
|
-
background:
|
|
436
|
+
background: var(--accent-soft);
|
|
426
437
|
font-weight: 650;
|
|
427
438
|
}
|
|
428
439
|
.markdown a {
|
|
429
|
-
color:
|
|
440
|
+
color: var(--info);
|
|
430
441
|
text-decoration: none;
|
|
431
442
|
}
|
|
432
443
|
.markdown a:hover {
|
|
@@ -436,6 +447,17 @@
|
|
|
436
447
|
margin: 0 0 var(--space-4);
|
|
437
448
|
overflow-x: auto;
|
|
438
449
|
overflow-y: hidden;
|
|
450
|
+
overflow-wrap: normal;
|
|
451
|
+
word-break: normal;
|
|
452
|
+
}
|
|
453
|
+
.markdown .katex {
|
|
454
|
+
overflow-wrap: normal;
|
|
455
|
+
word-break: normal;
|
|
456
|
+
}
|
|
457
|
+
.markdown .katex .text {
|
|
458
|
+
white-space: normal;
|
|
459
|
+
overflow-wrap: normal;
|
|
460
|
+
word-break: normal;
|
|
439
461
|
}
|
|
440
462
|
.markdown .katex-display:last-child {
|
|
441
463
|
margin-bottom: 0;
|
|
@@ -447,7 +469,7 @@
|
|
|
447
469
|
display: grid;
|
|
448
470
|
gap: var(--space-3);
|
|
449
471
|
align-content: end;
|
|
450
|
-
background:
|
|
472
|
+
background: var(--panel);
|
|
451
473
|
}
|
|
452
474
|
textarea {
|
|
453
475
|
min-width: 0;
|
|
@@ -457,15 +479,15 @@
|
|
|
457
479
|
border: 1px solid var(--line);
|
|
458
480
|
border-radius: var(--radius-sm);
|
|
459
481
|
padding: var(--space-4) var(--space-5);
|
|
460
|
-
background:
|
|
482
|
+
background: var(--panel-deep);
|
|
461
483
|
color: var(--ink);
|
|
462
484
|
font: inherit;
|
|
463
485
|
line-height: 1.4;
|
|
464
486
|
overflow-y: auto;
|
|
465
487
|
}
|
|
466
488
|
textarea:focus {
|
|
467
|
-
border-color:
|
|
468
|
-
box-shadow: 0 0 0 3px rgba(
|
|
489
|
+
border-color: var(--accent);
|
|
490
|
+
box-shadow: 0 0 0 3px rgba(8, 127, 154, 0.18);
|
|
469
491
|
outline: 0;
|
|
470
492
|
}
|
|
471
493
|
.actions {
|
|
@@ -501,8 +523,8 @@
|
|
|
501
523
|
text-overflow: ellipsis;
|
|
502
524
|
padding: var(--space-1) var(--space-4) var(--space-1) 18px;
|
|
503
525
|
border-radius: 999px;
|
|
504
|
-
background: rgba(
|
|
505
|
-
border: 1px solid rgba(
|
|
526
|
+
background: rgba(230, 246, 248, 0.96);
|
|
527
|
+
border: 1px solid rgba(8, 127, 154, 0.35);
|
|
506
528
|
font: inherit;
|
|
507
529
|
font-size: 12px;
|
|
508
530
|
cursor: pointer;
|
|
@@ -514,8 +536,8 @@
|
|
|
514
536
|
display: none;
|
|
515
537
|
}
|
|
516
538
|
.spinner:focus-visible {
|
|
517
|
-
border-color:
|
|
518
|
-
box-shadow: 0 0 0 3px rgba(
|
|
539
|
+
border-color: var(--accent);
|
|
540
|
+
box-shadow: 0 0 0 3px rgba(8, 127, 154, 0.18);
|
|
519
541
|
outline: 0;
|
|
520
542
|
}
|
|
521
543
|
.spinner-wrap:has(.spinner:not(:empty)) {
|
|
@@ -534,12 +556,12 @@
|
|
|
534
556
|
animation: spinner-pulse 1.2s cubic-bezier(0.4, 0, 0.2, 1) infinite;
|
|
535
557
|
}
|
|
536
558
|
.spinner.notify-enabled {
|
|
537
|
-
color:
|
|
538
|
-
background:
|
|
539
|
-
border-color:
|
|
559
|
+
color: var(--success);
|
|
560
|
+
background: var(--success-soft);
|
|
561
|
+
border-color: var(--success-line);
|
|
540
562
|
box-shadow:
|
|
541
|
-
inset 0 1px 2px rgba(
|
|
542
|
-
inset 0 0 0 1px rgba(
|
|
563
|
+
inset 0 1px 2px rgba(27, 57, 72, 0.08),
|
|
564
|
+
inset 0 0 0 1px rgba(36, 122, 82, 0.1);
|
|
543
565
|
}
|
|
544
566
|
.toast {
|
|
545
567
|
position: absolute;
|
|
@@ -548,11 +570,11 @@
|
|
|
548
570
|
z-index: 5;
|
|
549
571
|
width: max-content;
|
|
550
572
|
max-width: min(320px, calc(100vw - var(--space-6) * 2));
|
|
551
|
-
border: 1px solid
|
|
573
|
+
border: 1px solid var(--line-strong);
|
|
552
574
|
border-radius: var(--radius-sm);
|
|
553
|
-
background:
|
|
575
|
+
background: var(--panel-raised);
|
|
554
576
|
color: var(--ink);
|
|
555
|
-
box-shadow: 0 8px 20px rgba(
|
|
577
|
+
box-shadow: 0 8px 20px rgba(27, 57, 72, 0.14);
|
|
556
578
|
padding: var(--space-4) var(--space-6);
|
|
557
579
|
font-size: 12px;
|
|
558
580
|
opacity: 0;
|
|
@@ -577,14 +599,14 @@
|
|
|
577
599
|
}
|
|
578
600
|
@keyframes thinking-breathe {
|
|
579
601
|
0%, 100% {
|
|
580
|
-
border-color:
|
|
602
|
+
border-color: var(--success-line);
|
|
581
603
|
box-shadow: var(--entry-shadow);
|
|
582
604
|
}
|
|
583
605
|
50% {
|
|
584
|
-
border-color:
|
|
606
|
+
border-color: var(--success);
|
|
585
607
|
box-shadow:
|
|
586
|
-
0 0 0 2px rgba(
|
|
587
|
-
0 2px 7px rgba(
|
|
608
|
+
0 0 0 2px rgba(36, 122, 82, 0.14),
|
|
609
|
+
0 2px 7px rgba(27, 57, 72, 0.08);
|
|
588
610
|
}
|
|
589
611
|
}
|
|
590
612
|
@media (prefers-reduced-motion: reduce) {
|
|
@@ -683,12 +705,14 @@
|
|
|
683
705
|
const markdownRenderer = window.markdownit
|
|
684
706
|
? window.markdownit({html: false, linkify: true, breaks: false})
|
|
685
707
|
: null;
|
|
686
|
-
const
|
|
687
|
-
|
|
688
|
-
|
|
689
|
-
|
|
690
|
-
|
|
708
|
+
const mathDelimiters = [
|
|
709
|
+
{left: "$$", right: "$$", display: true},
|
|
710
|
+
{left: "\\[", right: "\\]", display: true},
|
|
711
|
+
{left: "\\(", right: "\\)", display: false},
|
|
712
|
+
{left: "$", right: "$", display: false},
|
|
691
713
|
];
|
|
714
|
+
const mathTokenPrefix = "\uE000math";
|
|
715
|
+
const mathTokenSuffix = "\uE001";
|
|
692
716
|
|
|
693
717
|
function relativeUrl(path) {
|
|
694
718
|
return new URL(path, window.location.href).toString();
|
|
@@ -725,41 +749,211 @@
|
|
|
725
749
|
root.textContent = source || "";
|
|
726
750
|
return;
|
|
727
751
|
}
|
|
728
|
-
|
|
729
|
-
|
|
730
|
-
markdownSource = markdownSource.split(delimiter).join(placeholder);
|
|
731
|
-
});
|
|
732
|
-
const dirtyHtml = markdownRenderer.render(markdownSource);
|
|
752
|
+
const protectedMath = protectMath(String(source || ""));
|
|
753
|
+
const dirtyHtml = markdownRenderer.render(protectedMath.source);
|
|
733
754
|
root.innerHTML = window.DOMPurify.sanitize(dirtyHtml, {
|
|
734
755
|
USE_PROFILES: {html: true},
|
|
735
756
|
ADD_ATTR: ["target", "rel"],
|
|
736
757
|
});
|
|
758
|
+
renderProtectedMath(root, protectedMath.expressions);
|
|
759
|
+
root.querySelectorAll("a").forEach((anchor) => {
|
|
760
|
+
anchor.target = "_blank";
|
|
761
|
+
anchor.rel = "noopener noreferrer";
|
|
762
|
+
});
|
|
763
|
+
}
|
|
764
|
+
|
|
765
|
+
function isEscapedAt(source, index) {
|
|
766
|
+
let slashCount = 0;
|
|
767
|
+
for (let cursor = index - 1; cursor >= 0 && source[cursor] === "\\"; cursor -= 1) {
|
|
768
|
+
slashCount += 1;
|
|
769
|
+
}
|
|
770
|
+
return slashCount % 2 === 1;
|
|
771
|
+
}
|
|
772
|
+
|
|
773
|
+
function countBackticks(source, index) {
|
|
774
|
+
let count = 0;
|
|
775
|
+
while (source[index + count] === "`") {
|
|
776
|
+
count += 1;
|
|
777
|
+
}
|
|
778
|
+
return count;
|
|
779
|
+
}
|
|
780
|
+
|
|
781
|
+
function findMathEnd(source, start, delimiter) {
|
|
782
|
+
let searchFrom = start + delimiter.left.length;
|
|
783
|
+
while (searchFrom < source.length) {
|
|
784
|
+
const end = source.indexOf(delimiter.right, searchFrom);
|
|
785
|
+
if (end < 0) {
|
|
786
|
+
return -1;
|
|
787
|
+
}
|
|
788
|
+
if (!isEscapedAt(source, end)) {
|
|
789
|
+
if (
|
|
790
|
+
delimiter.left === "$" &&
|
|
791
|
+
(source[end - 1] === "$" || source[end + 1] === "$")
|
|
792
|
+
) {
|
|
793
|
+
searchFrom = end + delimiter.right.length;
|
|
794
|
+
continue;
|
|
795
|
+
}
|
|
796
|
+
return end;
|
|
797
|
+
}
|
|
798
|
+
searchFrom = end + delimiter.right.length;
|
|
799
|
+
}
|
|
800
|
+
return -1;
|
|
801
|
+
}
|
|
802
|
+
|
|
803
|
+
function protectMath(source) {
|
|
804
|
+
const expressions = [];
|
|
805
|
+
let protectedSource = "";
|
|
806
|
+
let index = 0;
|
|
807
|
+
while (index < source.length) {
|
|
808
|
+
if (source[index] === "`") {
|
|
809
|
+
const tickCount = countBackticks(source, index);
|
|
810
|
+
const fence = "`".repeat(tickCount);
|
|
811
|
+
const close = source.indexOf(fence, index + tickCount);
|
|
812
|
+
if (close >= 0) {
|
|
813
|
+
const end = close + tickCount;
|
|
814
|
+
protectedSource += source.slice(index, end);
|
|
815
|
+
index = end;
|
|
816
|
+
continue;
|
|
817
|
+
}
|
|
818
|
+
}
|
|
819
|
+
|
|
820
|
+
let matched = null;
|
|
821
|
+
if (!isEscapedAt(source, index)) {
|
|
822
|
+
for (const delimiter of mathDelimiters) {
|
|
823
|
+
if (
|
|
824
|
+
source.indexOf(delimiter.left, index) !== index ||
|
|
825
|
+
(delimiter.left === "$" && source[index + 1] === "$")
|
|
826
|
+
) {
|
|
827
|
+
continue;
|
|
828
|
+
}
|
|
829
|
+
const end = findMathEnd(source, index, delimiter);
|
|
830
|
+
if (end > index + delimiter.left.length) {
|
|
831
|
+
matched = {
|
|
832
|
+
delimiter: delimiter,
|
|
833
|
+
start: index,
|
|
834
|
+
end: end,
|
|
835
|
+
};
|
|
836
|
+
break;
|
|
837
|
+
}
|
|
838
|
+
}
|
|
839
|
+
}
|
|
840
|
+
|
|
841
|
+
if (matched) {
|
|
842
|
+
const expressionIndex = expressions.length;
|
|
843
|
+
expressions.push({
|
|
844
|
+
body: source.slice(
|
|
845
|
+
matched.start + matched.delimiter.left.length,
|
|
846
|
+
matched.end,
|
|
847
|
+
),
|
|
848
|
+
delimiter: matched.delimiter,
|
|
849
|
+
});
|
|
850
|
+
protectedSource += mathTokenPrefix + expressionIndex + mathTokenSuffix;
|
|
851
|
+
index = matched.end + matched.delimiter.right.length;
|
|
852
|
+
continue;
|
|
853
|
+
}
|
|
854
|
+
|
|
855
|
+
protectedSource += source[index];
|
|
856
|
+
index += 1;
|
|
857
|
+
}
|
|
858
|
+
return {
|
|
859
|
+
source: protectedSource,
|
|
860
|
+
expressions: expressions,
|
|
861
|
+
};
|
|
862
|
+
}
|
|
863
|
+
|
|
864
|
+
function renderProtectedMath(root, expressions) {
|
|
865
|
+
if (!expressions.length) {
|
|
866
|
+
return;
|
|
867
|
+
}
|
|
868
|
+
const expressionByToken = new Map();
|
|
869
|
+
expressions.forEach((expression, index) => {
|
|
870
|
+
expressionByToken.set(
|
|
871
|
+
mathTokenPrefix + index + mathTokenSuffix,
|
|
872
|
+
expression,
|
|
873
|
+
);
|
|
874
|
+
});
|
|
875
|
+
const textWalker = document.createTreeWalker(root, NodeFilter.SHOW_TEXT);
|
|
876
|
+
const textNodes = [];
|
|
877
|
+
let textNode = textWalker.nextNode();
|
|
878
|
+
while (textNode) {
|
|
879
|
+
textNodes.push(textNode);
|
|
880
|
+
textNode = textWalker.nextNode();
|
|
881
|
+
}
|
|
882
|
+
for (const textNode of textNodes) {
|
|
883
|
+
let value = textNode.nodeValue || "";
|
|
884
|
+
let cursor = 0;
|
|
885
|
+
let tokenIndex = value.indexOf(mathTokenPrefix, cursor);
|
|
886
|
+
if (tokenIndex < 0) {
|
|
887
|
+
continue;
|
|
888
|
+
}
|
|
889
|
+
const fragment = document.createDocumentFragment();
|
|
890
|
+
while (tokenIndex >= 0) {
|
|
891
|
+
const tokenEnd = value.indexOf(mathTokenSuffix, tokenIndex);
|
|
892
|
+
if (tokenEnd < 0) {
|
|
893
|
+
break;
|
|
894
|
+
}
|
|
895
|
+
const token = value.slice(tokenIndex, tokenEnd + mathTokenSuffix.length);
|
|
896
|
+
const expression = expressionByToken.get(token);
|
|
897
|
+
if (!expression) {
|
|
898
|
+
break;
|
|
899
|
+
}
|
|
900
|
+
if (tokenIndex > cursor) {
|
|
901
|
+
fragment.appendChild(
|
|
902
|
+
document.createTextNode(value.slice(cursor, tokenIndex)),
|
|
903
|
+
);
|
|
904
|
+
}
|
|
905
|
+
const mathNode = document.createElement("span");
|
|
906
|
+
const sourceText =
|
|
907
|
+
expression.delimiter.left +
|
|
908
|
+
expression.body +
|
|
909
|
+
expression.delimiter.right;
|
|
910
|
+
if (window.renderMathInElement) {
|
|
911
|
+
mathNode.textContent = sourceText;
|
|
912
|
+
window.renderMathInElement(mathNode, {
|
|
913
|
+
delimiters: [
|
|
914
|
+
{
|
|
915
|
+
left: expression.delimiter.left,
|
|
916
|
+
right: expression.delimiter.right,
|
|
917
|
+
display: expression.delimiter.display,
|
|
918
|
+
},
|
|
919
|
+
],
|
|
920
|
+
throwOnError: false,
|
|
921
|
+
trust: false,
|
|
922
|
+
});
|
|
923
|
+
} else {
|
|
924
|
+
mathNode.textContent = expression.body;
|
|
925
|
+
}
|
|
926
|
+
fragment.appendChild(mathNode);
|
|
927
|
+
cursor = tokenEnd + mathTokenSuffix.length;
|
|
928
|
+
tokenIndex = value.indexOf(mathTokenPrefix, cursor);
|
|
929
|
+
}
|
|
930
|
+
if (cursor > 0) {
|
|
931
|
+
if (cursor < value.length) {
|
|
932
|
+
fragment.appendChild(document.createTextNode(value.slice(cursor)));
|
|
933
|
+
}
|
|
934
|
+
if (textNode.parentNode) {
|
|
935
|
+
textNode.parentNode.replaceChild(fragment, textNode);
|
|
936
|
+
}
|
|
937
|
+
}
|
|
938
|
+
}
|
|
939
|
+
restoreUnrenderedMathTokens(root, expressionByToken);
|
|
940
|
+
}
|
|
941
|
+
|
|
942
|
+
function restoreUnrenderedMathTokens(root, expressionByToken) {
|
|
737
943
|
const textWalker = document.createTreeWalker(root, NodeFilter.SHOW_TEXT);
|
|
738
944
|
let textNode = textWalker.nextNode();
|
|
739
945
|
while (textNode) {
|
|
740
946
|
let value = textNode.nodeValue || "";
|
|
741
|
-
|
|
742
|
-
|
|
947
|
+
expressionByToken.forEach((expression, token) => {
|
|
948
|
+
const sourceText =
|
|
949
|
+
expression.delimiter.left +
|
|
950
|
+
expression.body +
|
|
951
|
+
expression.delimiter.right;
|
|
952
|
+
value = value.split(token).join(sourceText);
|
|
743
953
|
});
|
|
744
954
|
textNode.nodeValue = value;
|
|
745
955
|
textNode = textWalker.nextNode();
|
|
746
956
|
}
|
|
747
|
-
if (window.renderMathInElement) {
|
|
748
|
-
window.renderMathInElement(root, {
|
|
749
|
-
delimiters: [
|
|
750
|
-
{left: "$$", right: "$$", display: true},
|
|
751
|
-
{left: "\\[", right: "\\]", display: true},
|
|
752
|
-
{left: "\\(", right: "\\)", display: false},
|
|
753
|
-
{left: "$", right: "$", display: false},
|
|
754
|
-
],
|
|
755
|
-
throwOnError: false,
|
|
756
|
-
trust: false,
|
|
757
|
-
});
|
|
758
|
-
}
|
|
759
|
-
root.querySelectorAll("a").forEach((anchor) => {
|
|
760
|
-
anchor.target = "_blank";
|
|
761
|
-
anchor.rel = "noopener noreferrer";
|
|
762
|
-
});
|
|
763
957
|
}
|
|
764
958
|
|
|
765
959
|
function loadChatWidth() {
|
|
File without changes
|
|
File without changes
|
|
File without changes
|