codex-overleaf-link 1.8.6 → 1.9.0
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/README.md +45 -21
- package/bin/codex-overleaf-link.mjs +58 -0
- package/extension/assets/icons/codex-overleaf-dialog-icon.png +0 -0
- package/extension/assets/icons/codex-overleaf-icon.png +0 -0
- package/extension/assets/icons/icon128.png +0 -0
- package/extension/assets/icons/icon16.png +0 -0
- package/extension/assets/icons/icon32.png +0 -0
- package/extension/assets/icons/icon48.png +0 -0
- package/extension/bootstrap/background.js +404 -0
- package/extension/bootstrap/manifest.template.json +51 -0
- package/extension/bootstrap/popup.css +26 -0
- package/extension/bootstrap/popup.html +38 -0
- package/extension/bootstrap/popup.js +44 -0
- package/extension/bootstrap/runtimeContext.js +2 -0
- package/extension/runtime-manifest.json +60 -0
- package/extension/src/background.js +532 -0
- package/extension/src/content/applyResultFormatters.js +387 -0
- package/extension/src/content/composerAttachments.js +522 -0
- package/extension/src/content/composerPanel.js +254 -0
- package/extension/src/content/contentRuntime.js +8895 -0
- package/extension/src/content/contextTray.js +686 -0
- package/extension/src/content/diagnosticsController.js +659 -0
- package/extension/src/content/diagnosticsPanel.js +342 -0
- package/extension/src/content/diffReviewPanel.js +797 -0
- package/extension/src/content/localSkillsPanel.js +280 -0
- package/extension/src/content/markdownText.js +606 -0
- package/extension/src/content/mirrorHealth.js +92 -0
- package/extension/src/content/modelPicker.js +489 -0
- package/extension/src/content/nativeChannel.js +62 -0
- package/extension/src/content/otWarmMirror.js +964 -0
- package/extension/src/content/otWarmMirrorController.js +174 -0
- package/extension/src/content/panelMaintenance.js +367 -0
- package/extension/src/content/panelRenderer.js +253 -0
- package/extension/src/content/recentProjects.js +1063 -0
- package/extension/src/content/reviewHunks.js +247 -0
- package/extension/src/content/runController.js +242 -0
- package/extension/src/content/runTimelineView.js +1126 -0
- package/extension/src/content/sessionManager.js +487 -0
- package/extension/src/content/sessionPanel.js +263 -0
- package/extension/src/content/settingsPanel.js +527 -0
- package/extension/src/content/themeController.js +91 -0
- package/extension/src/content/updateIdle.js +67 -0
- package/extension/src/content/writebackController.js +300 -0
- package/extension/src/content/writebackOrchestrator.js +850 -0
- package/extension/src/contentScript.js +8 -0
- package/extension/src/page/compileBridge.js +460 -0
- package/extension/src/page/overleafCapabilities.js +100 -0
- package/extension/src/page/overleafEditor.js +282 -0
- package/extension/src/page/overleafProjectSnapshot.js +234 -0
- package/extension/src/page/overleafRealtimeObserver.js +491 -0
- package/extension/src/page/pageBridgeCapability.js +71 -0
- package/extension/src/page/snapshotRouter.js +948 -0
- package/extension/src/page/trackedChangesLifecycle.js +1506 -0
- package/extension/src/page/treeOperations.js +1584 -0
- package/extension/src/page/writeGuard.js +142 -0
- package/extension/src/page/writebackRouter.js +1934 -0
- package/extension/src/pageBridge.js +2224 -0
- package/extension/src/popup.js +247 -0
- package/extension/src/shared/compatibility.js +1 -1
- package/extension/styles/panel.css +4048 -0
- package/native-host/src/index.js +9 -2
- package/native-host/src/managedInstall.js +393 -0
- package/native-host/src/managedLauncherRuntime.js +71 -0
- package/native-host/src/nativeHostPlatform.js +16 -0
- package/native-host/src/runtimeInstaller.js +6 -1
- package/native-host/src/taskRunnerRuntime.js +8 -0
- package/native-host/src/updateArchive.js +253 -0
- package/native-host/src/updateManager.js +548 -0
- package/native-host/src/updateTrust.js +156 -0
- package/package.json +11 -2
- package/scripts/install-managed.mjs +64 -0
- package/scripts/uninstall-managed.mjs +48 -0
|
@@ -0,0 +1,253 @@
|
|
|
1
|
+
(function initCodexOverleafPanelRenderer() {
|
|
2
|
+
'use strict';
|
|
3
|
+
|
|
4
|
+
const ROOT_CLASS = 'codex-overleaf-panel-mounted';
|
|
5
|
+
const RESIZE_CLASS = 'codex-overleaf-panel-resizing';
|
|
6
|
+
const COMPACT_CLASS = 'codex-overleaf-panel-compact';
|
|
7
|
+
|
|
8
|
+
function codexIcon(name) {
|
|
9
|
+
const icons = {
|
|
10
|
+
refresh: '<path d="M4.2 5.3A5 5 0 1 1 3.6 10"/><path d="M4.2 2.2v3.1H1.1"/>',
|
|
11
|
+
plus: '<path d="M8 3.2v9.6"/><path d="M3.2 8h9.6"/>',
|
|
12
|
+
settings: '<path d="M3.4 5.2h5.9"/><path d="M11.7 5.2h.9"/><path d="M10.1 3.6v3.2"/><path d="M3.4 10.8h1"/><path d="M6.8 10.8h5.8"/><path d="M5.9 9.2v3.2"/>'
|
|
13
|
+
};
|
|
14
|
+
const safeName = Object.prototype.hasOwnProperty.call(icons, name) ? name : 'settings';
|
|
15
|
+
return `<span class="codex-icon codex-icon-${safeName}" aria-hidden="true"><svg viewBox="0 0 16 16" focusable="false">${icons[safeName]}</svg></span>`;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
function create(options = {}) {
|
|
19
|
+
const doc = options.document || document;
|
|
20
|
+
const container = options.container || doc.documentElement;
|
|
21
|
+
const panelEl = doc.createElement('aside');
|
|
22
|
+
const callbacks = options.callbacks || {};
|
|
23
|
+
const instance = {
|
|
24
|
+
panelEl,
|
|
25
|
+
callbacks,
|
|
26
|
+
defaultWidth: options.defaultWidth || 380,
|
|
27
|
+
minWidth: options.minWidth || 340,
|
|
28
|
+
maxWidth: options.maxWidth || 760,
|
|
29
|
+
pageMinWidth: options.pageMinWidth || 520,
|
|
30
|
+
lastDesktopWidth: options.initialWidth || options.defaultWidth || 380,
|
|
31
|
+
listeners: [],
|
|
32
|
+
document: doc,
|
|
33
|
+
window: options.window || window
|
|
34
|
+
};
|
|
35
|
+
|
|
36
|
+
panelEl.id = options.panelId || 'codex-overleaf-panel';
|
|
37
|
+
panelEl.dataset.view = 'session';
|
|
38
|
+
panelEl.innerHTML = `
|
|
39
|
+
<div class="codex-panel-resize-handle" data-panel-resize-handle title="Drag to resize the Codex panel. Double click to reset." aria-label="Drag to resize the Codex panel. Double click to reset." role="separator"></div>
|
|
40
|
+
<div class="codex-vscode-head" data-panel-header>
|
|
41
|
+
<div class="codex-vscode-title">CODEX</div>
|
|
42
|
+
<div class="codex-vscode-head-actions" aria-label="Codex actions">
|
|
43
|
+
<button type="button" data-refresh title="Refresh current file status. This will not sync or modify files." aria-label="Refresh current file status. This will not sync or modify files.">${codexIcon('refresh')}</button>
|
|
44
|
+
<div data-diagnostics-slot></div>
|
|
45
|
+
<button type="button" data-new-session title="New Session" aria-label="New Session">${codexIcon('plus')}</button>
|
|
46
|
+
<button type="button" data-custom-instructions-settings title="Project Settings" aria-label="Project Settings" aria-expanded="false">${codexIcon('settings')}</button>
|
|
47
|
+
</div>
|
|
48
|
+
</div>
|
|
49
|
+
<div data-settings-slot></div>
|
|
50
|
+
<div class="codex-vscode-main" data-main>
|
|
51
|
+
<div data-session-slot></div>
|
|
52
|
+
<div class="codex-toast-region" data-toast-region aria-live="polite" aria-atomic="false"></div>
|
|
53
|
+
<section class="codex-thread-section">
|
|
54
|
+
<div class="codex-thread-title" data-session-label>
|
|
55
|
+
<button type="button" class="codex-thread-title-trigger" data-session-menu-trigger aria-haspopup="menu" aria-expanded="false">
|
|
56
|
+
<span class="codex-thread-title-text" data-session-label-text></span>
|
|
57
|
+
<span class="codex-thread-title-chevron" aria-hidden="true">▾</span>
|
|
58
|
+
</button>
|
|
59
|
+
<input type="text" class="codex-thread-title-input" data-session-rename-input maxlength="80" hidden>
|
|
60
|
+
<div class="codex-thread-title-actions">
|
|
61
|
+
<button type="button" class="codex-thread-title-action" data-session-rename title="Rename session" aria-label="Rename session">✎</button>
|
|
62
|
+
<button type="button" class="codex-thread-title-action codex-thread-title-action--delete" data-session-delete title="Delete session" aria-label="Delete session">×</button>
|
|
63
|
+
</div>
|
|
64
|
+
<div class="codex-session-menu" data-session-menu hidden></div>
|
|
65
|
+
</div>
|
|
66
|
+
<div class="col-log" data-log></div>
|
|
67
|
+
</section>
|
|
68
|
+
</div>
|
|
69
|
+
<div class="codex-probe-line" data-probe-status>Checking Overleaf state...</div>
|
|
70
|
+
<div data-composer-slot></div>
|
|
71
|
+
`;
|
|
72
|
+
|
|
73
|
+
container.append(panelEl);
|
|
74
|
+
doc.documentElement.classList.add(ROOT_CLASS);
|
|
75
|
+
|
|
76
|
+
instance.headerEl = panelEl.querySelector('[data-panel-header]');
|
|
77
|
+
instance.bodyEl = panelEl.querySelector('[data-main]');
|
|
78
|
+
instance.diagnosticsSlot = panelEl.querySelector('[data-diagnostics-slot]');
|
|
79
|
+
instance.settingsSlot = panelEl.querySelector('[data-settings-slot]');
|
|
80
|
+
instance.sessionSlot = panelEl.querySelector('[data-session-slot]');
|
|
81
|
+
instance.composerSlot = panelEl.querySelector('[data-composer-slot]');
|
|
82
|
+
|
|
83
|
+
bind(instance, panelEl, 'click', event => event.stopPropagation());
|
|
84
|
+
bind(instance, panelEl, 'mousedown', event => event.stopPropagation());
|
|
85
|
+
bind(instance, panelEl.querySelector('[data-refresh]'), 'click', () => callbacks.onRefresh?.());
|
|
86
|
+
bind(instance, panelEl.querySelector('[data-new-session]'), 'click', () => callbacks.onNewSession?.());
|
|
87
|
+
bind(instance, panelEl.querySelector('[data-custom-instructions-settings]'), 'click', () => callbacks.onSettingsClick?.());
|
|
88
|
+
bind(instance, panelEl.querySelector('[data-panel-resize-handle]'), 'pointerdown', event => startResize(instance, event));
|
|
89
|
+
bind(instance, panelEl.querySelector('[data-panel-resize-handle]'), 'dblclick', event => {
|
|
90
|
+
event?.preventDefault?.();
|
|
91
|
+
if (isCompactViewport(instance)) {
|
|
92
|
+
return;
|
|
93
|
+
}
|
|
94
|
+
const width = setWidth(instance, instance.defaultWidth, { notify: false });
|
|
95
|
+
callbacks.onWidthChange?.(width, { persist: true });
|
|
96
|
+
});
|
|
97
|
+
bind(instance, instance.window, 'resize', () => {
|
|
98
|
+
setWidth(instance, instance.lastDesktopWidth || instance.defaultWidth, { notify: true, persist: false });
|
|
99
|
+
});
|
|
100
|
+
|
|
101
|
+
setWidth(instance, options.initialWidth || instance.defaultWidth, { notify: false });
|
|
102
|
+
|
|
103
|
+
return {
|
|
104
|
+
panelEl,
|
|
105
|
+
headerEl: instance.headerEl,
|
|
106
|
+
bodyEl: instance.bodyEl,
|
|
107
|
+
diagnosticsSlot: instance.diagnosticsSlot,
|
|
108
|
+
settingsSlot: instance.settingsSlot,
|
|
109
|
+
sessionSlot: instance.sessionSlot,
|
|
110
|
+
composerSlot: instance.composerSlot,
|
|
111
|
+
setView: view => { panelEl.dataset.view = view; },
|
|
112
|
+
destroy: () => destroy(instance),
|
|
113
|
+
_instance: instance
|
|
114
|
+
};
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
function bind(instance, target, type, listener, options) {
|
|
118
|
+
if (!target?.addEventListener) {
|
|
119
|
+
return;
|
|
120
|
+
}
|
|
121
|
+
target.addEventListener(type, listener, options);
|
|
122
|
+
instance.listeners.push({ target, type, listener, options });
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
function startResize(instance, event) {
|
|
126
|
+
if (event.button !== undefined && event.button !== 0) {
|
|
127
|
+
return;
|
|
128
|
+
}
|
|
129
|
+
event.preventDefault();
|
|
130
|
+
if (isCompactViewport(instance)) {
|
|
131
|
+
return;
|
|
132
|
+
}
|
|
133
|
+
const doc = instance.document;
|
|
134
|
+
const startX = event.clientX;
|
|
135
|
+
const startWidth = instance.panelEl?.getBoundingClientRect?.().width || instance.defaultWidth;
|
|
136
|
+
const handle = event.currentTarget;
|
|
137
|
+
let latestWidth = startWidth;
|
|
138
|
+
|
|
139
|
+
doc.documentElement.classList.add(RESIZE_CLASS);
|
|
140
|
+
handle?.setPointerCapture?.(event.pointerId);
|
|
141
|
+
|
|
142
|
+
const onPointerMove = moveEvent => {
|
|
143
|
+
latestWidth = setWidth(instance, startWidth + (startX - moveEvent.clientX), { notify: false });
|
|
144
|
+
};
|
|
145
|
+
const onPointerUp = () => {
|
|
146
|
+
doc.removeEventListener('pointermove', onPointerMove, true);
|
|
147
|
+
doc.removeEventListener('pointerup', onPointerUp, true);
|
|
148
|
+
doc.documentElement.classList.remove(RESIZE_CLASS);
|
|
149
|
+
instance.callbacks.onWidthChange?.(latestWidth, { persist: true });
|
|
150
|
+
};
|
|
151
|
+
|
|
152
|
+
doc.addEventListener('pointermove', onPointerMove, true);
|
|
153
|
+
doc.addEventListener('pointerup', onPointerUp, true);
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
function setWidth(target, width, options = {}) {
|
|
157
|
+
const instance = target?._instance || target;
|
|
158
|
+
if (!instance) {
|
|
159
|
+
return 0;
|
|
160
|
+
}
|
|
161
|
+
const nextWidth = clampWidth(instance, width);
|
|
162
|
+
const compact = updateCompactMode(instance);
|
|
163
|
+
instance.document.documentElement.style.setProperty('--codex-overleaf-panel-width', `${nextWidth}px`);
|
|
164
|
+
if (!compact) {
|
|
165
|
+
instance.lastDesktopWidth = nextWidth;
|
|
166
|
+
}
|
|
167
|
+
if (options.notify !== false) {
|
|
168
|
+
instance.callbacks.onWidthChange?.(nextWidth, { persist: !compact && options.persist !== false });
|
|
169
|
+
}
|
|
170
|
+
return nextWidth;
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
function clampWidth(instance, width) {
|
|
174
|
+
const viewportWidth = Number(instance.window?.innerWidth);
|
|
175
|
+
if (isCompactViewport(instance)) {
|
|
176
|
+
const overlayMax = Number.isFinite(viewportWidth)
|
|
177
|
+
? Math.max(240, viewportWidth - 24)
|
|
178
|
+
: instance.minWidth;
|
|
179
|
+
const numericCompactWidth = Number(width);
|
|
180
|
+
const compactWidth = Number.isFinite(numericCompactWidth)
|
|
181
|
+
? numericCompactWidth
|
|
182
|
+
: instance.lastDesktopWidth || instance.defaultWidth;
|
|
183
|
+
return Math.round(Math.min(instance.maxWidth, overlayMax, Math.max(Math.min(instance.minWidth, overlayMax), compactWidth)));
|
|
184
|
+
}
|
|
185
|
+
const viewportMax = Number.isFinite(viewportWidth)
|
|
186
|
+
? Math.max(instance.minWidth, viewportWidth - instance.pageMinWidth)
|
|
187
|
+
: instance.maxWidth;
|
|
188
|
+
const maxWidth = Math.min(instance.maxWidth, viewportMax);
|
|
189
|
+
const numericWidth = Number(width);
|
|
190
|
+
if (!Number.isFinite(numericWidth)) {
|
|
191
|
+
return instance.defaultWidth;
|
|
192
|
+
}
|
|
193
|
+
return Math.round(Math.min(maxWidth, Math.max(instance.minWidth, numericWidth)));
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
function isCompactViewport(instance) {
|
|
197
|
+
const viewportWidth = Number(instance.window?.innerWidth);
|
|
198
|
+
return Number.isFinite(viewportWidth) && viewportWidth < instance.minWidth + instance.pageMinWidth;
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
function updateCompactMode(instance) {
|
|
202
|
+
const compact = isCompactViewport(instance);
|
|
203
|
+
instance.document.documentElement.classList.toggle(COMPACT_CLASS, compact);
|
|
204
|
+
if (!compact) {
|
|
205
|
+
instance.document.documentElement.classList.remove(COMPACT_CLASS);
|
|
206
|
+
}
|
|
207
|
+
return compact;
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
function setVisible(panelEl, visible) {
|
|
211
|
+
panelEl?.classList?.toggle('is-open', Boolean(visible));
|
|
212
|
+
document.documentElement.classList.toggle(ROOT_CLASS, Boolean(visible));
|
|
213
|
+
if (!visible) {
|
|
214
|
+
document.documentElement.classList.remove(RESIZE_CLASS, COMPACT_CLASS);
|
|
215
|
+
}
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
function setBadge(headerEl, badge = {}) {
|
|
219
|
+
const actions = headerEl?.querySelector?.('.codex-vscode-head-actions');
|
|
220
|
+
if (!actions) {
|
|
221
|
+
return;
|
|
222
|
+
}
|
|
223
|
+
actions.querySelector('[data-panel-header-badge]')?.remove();
|
|
224
|
+
if (!badge || badge.type === 'none') {
|
|
225
|
+
return;
|
|
226
|
+
}
|
|
227
|
+
const button = document.createElement('button');
|
|
228
|
+
button.type = 'button';
|
|
229
|
+
button.dataset.panelHeaderBadge = badge.type || 'info';
|
|
230
|
+
button.title = badge.tooltip || '';
|
|
231
|
+
button.setAttribute('aria-label', badge.tooltip || badge.type || 'status');
|
|
232
|
+
button.textContent = badge.type === 'update' ? '!' : '?';
|
|
233
|
+
if (typeof badge.onClick === 'function') {
|
|
234
|
+
button.addEventListener('click', badge.onClick);
|
|
235
|
+
}
|
|
236
|
+
actions.prepend(button);
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
function destroy(instance) {
|
|
240
|
+
for (const { target, type, listener, options } of instance.listeners.splice(0)) {
|
|
241
|
+
target.removeEventListener?.(type, listener, options);
|
|
242
|
+
}
|
|
243
|
+
instance.panelEl?.remove?.();
|
|
244
|
+
instance.document.documentElement.classList.remove(ROOT_CLASS, RESIZE_CLASS, COMPACT_CLASS);
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
window.CodexOverleafPanelRenderer = {
|
|
248
|
+
create,
|
|
249
|
+
setVisible,
|
|
250
|
+
setBadge,
|
|
251
|
+
setWidth
|
|
252
|
+
};
|
|
253
|
+
})();
|