codex-overleaf-link 2.2.1 → 2.3.1

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.
Files changed (79) hide show
  1. package/README.md +25 -23
  2. package/extension/bootstrap/manifest.template.json +1 -1
  3. package/extension/runtime-manifest.json +5 -71
  4. package/extension/src/background.js +67 -63
  5. package/extension/src/backgroundUpdateCoordinator.js +128 -66
  6. package/extension/src/content/applyResultFormatters.js +2 -3
  7. package/extension/src/content/composerPanel.js +0 -2
  8. package/extension/src/content/contentRuntime.js +757 -1558
  9. package/extension/src/content/contextTray.js +4 -6
  10. package/extension/src/content/diagnosticsController.js +1 -2
  11. package/extension/src/content/diffReviewPanel.js +14 -13
  12. package/extension/src/content/generated/content.bundle.js +41605 -0
  13. package/extension/src/content/generated/content.bundle.meta.json +103 -0
  14. package/extension/src/content/legacyGlobalRegistry.js +129 -0
  15. package/extension/src/content/markdownText.js +17 -17
  16. package/extension/src/content/mathText.js +155 -9
  17. package/extension/src/content/modelPicker.js +1 -1
  18. package/extension/src/content/modelPickerSupport.js +10 -5
  19. package/extension/src/content/moduleRegistryKernel.js +125 -0
  20. package/extension/src/content/nativeCompatibilityController.js +313 -0
  21. package/extension/src/content/otWarmMirror.js +8 -6
  22. package/extension/src/content/pageBridgeClient.js +224 -0
  23. package/extension/src/content/panelMaintenance.js +8 -3
  24. package/extension/src/content/postNavigationSettlementPersistence.js +100 -0
  25. package/extension/src/content/projectProviderSelection.js +4 -12
  26. package/extension/src/content/projectSessionCleanup.js +3 -3
  27. package/extension/src/content/providerSettingsCoordinator.js +59 -26
  28. package/extension/src/content/providerSettingsDialog.js +30 -18
  29. package/extension/src/content/recentProjects.js +15 -23
  30. package/extension/src/content/runGuidanceController.js +1 -1
  31. package/extension/src/content/runQueueScheduler.js +129 -29
  32. package/extension/src/content/runSettlementPersistence.js +51 -0
  33. package/extension/src/content/runTimelineView.js +17 -8
  34. package/extension/src/content/scopedPersistenceCoordinator.js +100 -0
  35. package/extension/src/content/scopedPersistenceDetachedCommit.js +47 -0
  36. package/extension/src/content/scopedPersistencePanelState.js +111 -0
  37. package/extension/src/content/sessionManager.js +15 -12
  38. package/extension/src/content/sessionPersistence.js +67 -8
  39. package/extension/src/content/updateNotice.js +10 -4
  40. package/extension/src/content/writebackOrchestrator.js +89 -68
  41. package/extension/src/contentScript.js +5 -1
  42. package/extension/src/page/trackedChangesLifecycle.js +16 -5
  43. package/extension/src/page/writebackRouter.js +6 -2
  44. package/extension/src/pageBridge.js +47 -98
  45. package/extension/src/shared/agentTranscript.js +18 -8
  46. package/extension/src/shared/compatibility.js +1 -1
  47. package/extension/src/shared/governanceRules.js +1 -1
  48. package/extension/src/shared/i18n.js +2 -4
  49. package/extension/src/shared/managedUpdateProjection.js +337 -0
  50. package/extension/src/shared/nativeRequestIdentity.js +60 -0
  51. package/extension/src/shared/otText.js +0 -19
  52. package/extension/src/shared/pageRpcContract.js +136 -0
  53. package/extension/src/shared/runExecutionSnapshot.js +187 -0
  54. package/extension/src/shared/runExecutionSnapshotCodec.js +171 -0
  55. package/extension/src/shared/runInputQueue.js +81 -34
  56. package/extension/src/shared/scopedPersistenceBrowserAdapter.js +79 -0
  57. package/extension/src/shared/scopedPersistenceQueuePolicy.js +200 -0
  58. package/extension/src/shared/scopedPersistenceReceipt.js +60 -0
  59. package/extension/src/shared/scopedPersistenceTransaction.js +241 -0
  60. package/extension/src/shared/sessionState.js +110 -59
  61. package/extension/src/shared/settlementFacts.js +351 -0
  62. package/extension/src/shared/storageDb.js +25 -10
  63. package/extension/src/shared/storageMigration.js +275 -61
  64. package/extension/src/shared/storageSessionClaims.js +60 -0
  65. package/extension/src/shared/updateConsent.js +4 -0
  66. package/extension/src/shared/updateRevocationIntent.js +109 -0
  67. package/extension/src/shared/writebackEvidenceProjection.js +150 -0
  68. package/extension/src/shared/writebackOperationEvidence.js +153 -0
  69. package/extension/src/shared/writebackSettlement.js +727 -0
  70. package/extension/styles/panel.css +18 -8
  71. package/native-host/src/codexPromptAssembly.js +1 -1
  72. package/native-host/src/codexRuntimeIdentity.js +1 -1
  73. package/native-host/src/codexSessionRunner.js +7 -13
  74. package/native-host/src/index.js +3 -69
  75. package/native-host/src/managedInstall.js +50 -8
  76. package/native-host/src/nativeTransportEnvelope.js +148 -0
  77. package/native-host/src/taskRunnerRuntime.js +14 -84
  78. package/native-host/src/updateManager.js +36 -1
  79. package/package.json +13 -5
@@ -0,0 +1,103 @@
1
+ {
2
+ "schemaVersion": 1,
3
+ "entry": "extension/entries/content-entry.mjs",
4
+ "output": "extension/src/content/generated/content.bundle.js",
5
+ "sourceDigest": "ddbc07ac8d34d864aa3648c53211c5858e0312a73df815a0392bc52ec5eac1cc",
6
+ "outputDigest": "42051c8624bdfca3094c8bef2430094e55b7e1ec49d475ac27f6df14629bf313",
7
+ "byteLength": 2285557,
8
+ "inputs": [
9
+ "extension/entries/content-entry.mjs",
10
+ "extension/src/content/activeTurnControl.js",
11
+ "extension/src/content/applyResultFormatters.js",
12
+ "extension/src/content/composerAttachments.js",
13
+ "extension/src/content/composerPanel.js",
14
+ "extension/src/content/contentRuntime.js",
15
+ "extension/src/content/contextTray.js",
16
+ "extension/src/content/diagnosticsController.js",
17
+ "extension/src/content/diagnosticsPanel.js",
18
+ "extension/src/content/diffReviewPanel.js",
19
+ "extension/src/content/legacyGlobalRegistry.js",
20
+ "extension/src/content/localSkillsPanel.js",
21
+ "extension/src/content/markdownDomRenderer.js",
22
+ "extension/src/content/markdownText.js",
23
+ "extension/src/content/mathText.js",
24
+ "extension/src/content/mirrorHealth.js",
25
+ "extension/src/content/modelPicker.js",
26
+ "extension/src/content/modelPickerSupport.js",
27
+ "extension/src/content/moduleRegistryKernel.js",
28
+ "extension/src/content/nativeChannel.js",
29
+ "extension/src/content/nativeCompatibilityController.js",
30
+ "extension/src/content/otWarmMirror.js",
31
+ "extension/src/content/otWarmMirrorController.js",
32
+ "extension/src/content/pageBridgeClient.js",
33
+ "extension/src/content/panelMaintenance.js",
34
+ "extension/src/content/panelRenderer.js",
35
+ "extension/src/content/pendingInputView.js",
36
+ "extension/src/content/postNavigationSettlementPersistence.js",
37
+ "extension/src/content/projectProviderSelection.js",
38
+ "extension/src/content/projectSessionCleanup.js",
39
+ "extension/src/content/projectSettingsCoordinator.js",
40
+ "extension/src/content/providerSettingsCoordinator.js",
41
+ "extension/src/content/providerSettingsDialog.js",
42
+ "extension/src/content/recentProjects.js",
43
+ "extension/src/content/reviewHunks.js",
44
+ "extension/src/content/runController.js",
45
+ "extension/src/content/runGuidanceController.js",
46
+ "extension/src/content/runGuidanceView.js",
47
+ "extension/src/content/runQueueScheduler.js",
48
+ "extension/src/content/runSettlementPersistence.js",
49
+ "extension/src/content/runTimelineView.js",
50
+ "extension/src/content/scopedPersistenceCoordinator.js",
51
+ "extension/src/content/scopedPersistenceDetachedCommit.js",
52
+ "extension/src/content/scopedPersistencePanelState.js",
53
+ "extension/src/content/sessionManager.js",
54
+ "extension/src/content/sessionMenuView.js",
55
+ "extension/src/content/sessionPanel.js",
56
+ "extension/src/content/sessionPersistence.js",
57
+ "extension/src/content/settingsPanel.js",
58
+ "extension/src/content/themeController.js",
59
+ "extension/src/content/updateIdle.js",
60
+ "extension/src/content/updateNotice.js",
61
+ "extension/src/content/writebackController.js",
62
+ "extension/src/content/writebackOrchestrator.js",
63
+ "extension/src/shared/agentTranscript.js",
64
+ "extension/src/shared/auditRecords.js",
65
+ "extension/src/shared/compatibility.js",
66
+ "extension/src/shared/compileAdapter.js",
67
+ "extension/src/shared/failureReasons.js",
68
+ "extension/src/shared/governanceRules.js",
69
+ "extension/src/shared/i18n.js",
70
+ "extension/src/shared/lineReferences.js",
71
+ "extension/src/shared/managedUpdateProjection.js",
72
+ "extension/src/shared/models.js",
73
+ "extension/src/shared/otText.js",
74
+ "extension/src/shared/pageRpcContract.js",
75
+ "extension/src/shared/pathRedaction.js",
76
+ "extension/src/shared/projectFiles.js",
77
+ "extension/src/shared/providerProfiles.js",
78
+ "extension/src/shared/reviewing.js",
79
+ "extension/src/shared/runExecutionSnapshot.js",
80
+ "extension/src/shared/runExecutionSnapshotCodec.js",
81
+ "extension/src/shared/runInputQueue.js",
82
+ "extension/src/shared/scopedPersistenceBrowserAdapter.js",
83
+ "extension/src/shared/scopedPersistenceQueuePolicy.js",
84
+ "extension/src/shared/scopedPersistenceReceipt.js",
85
+ "extension/src/shared/scopedPersistenceTransaction.js",
86
+ "extension/src/shared/sensitiveScan.js",
87
+ "extension/src/shared/sessionState.js",
88
+ "extension/src/shared/settlementFacts.js",
89
+ "extension/src/shared/staleGuard.js",
90
+ "extension/src/shared/storageDb.js",
91
+ "extension/src/shared/storageKeys.js",
92
+ "extension/src/shared/storageMigration.js",
93
+ "extension/src/shared/storageRunActions.js",
94
+ "extension/src/shared/storageSessionClaims.js",
95
+ "extension/src/shared/summary.js",
96
+ "extension/src/shared/undoOperations.js",
97
+ "extension/src/shared/writebackEvidenceProjection.js",
98
+ "extension/src/shared/writebackOperationEvidence.js",
99
+ "extension/src/shared/writebackSettlement.js",
100
+ "extension/vendor/katex/katex.min.js",
101
+ "extension/vendor/markdown-it/markdown-it.min.js"
102
+ ]
103
+ }
@@ -0,0 +1,129 @@
1
+ (function initCodexOverleafLegacyGlobalRegistry(root, factory) {
2
+ 'use strict';
3
+
4
+ const api = factory();
5
+ if (typeof module === 'object' && module.exports) {
6
+ module.exports = api;
7
+ }
8
+ if (root) {
9
+ root.CodexOverleafLegacyGlobalRegistry = api;
10
+ }
11
+ })(typeof window !== 'undefined' ? window : globalThis, function legacyGlobalRegistryFactory() {
12
+ 'use strict';
13
+
14
+ const REQUIRED_MODULES = Object.freeze([
15
+ 'ActiveTurnControl',
16
+ 'AgentTranscript',
17
+ 'ApplyResultFormatters',
18
+ 'AuditRecords',
19
+ 'Compatibility',
20
+ 'ComposerAttachments',
21
+ 'ComposerPanel',
22
+ 'ContentRuntime',
23
+ 'ContextTray',
24
+ 'DiagnosticsController',
25
+ 'DiagnosticsPanel',
26
+ 'DiffReviewPanel',
27
+ 'FailureReasons',
28
+ 'GovernanceRules',
29
+ 'I18n',
30
+ 'LineReferences',
31
+ 'LocalSkillsPanel',
32
+ 'MarkdownText',
33
+ 'MirrorHealth',
34
+ 'ModelPicker',
35
+ 'NativeChannel',
36
+ 'NativeCompatibilityController',
37
+ 'OtWarmMirror',
38
+ 'OtWarmMirrorController',
39
+ 'PageBridgeClient',
40
+ 'PageRpcContract',
41
+ 'PanelMaintenance',
42
+ 'PanelRenderer',
43
+ 'PendingInputView',
44
+ 'PostNavigationSettlementPersistence',
45
+ 'ProjectFiles',
46
+ 'ProjectProviderSelection',
47
+ 'ProjectSettingsCoordinator',
48
+ 'ProviderSettingsCoordinator',
49
+ 'RecentProjects',
50
+ 'ReviewHunks',
51
+ 'RunController',
52
+ 'RunExecutionSnapshot',
53
+ 'RunGuidanceController',
54
+ 'RunInputQueue',
55
+ 'RunQueueScheduler',
56
+ 'RunSettlementPersistence',
57
+ 'RunTimelineView',
58
+ 'ScopedPersistenceCoordinator',
59
+ 'ScopedPersistenceTransaction',
60
+ 'SensitiveScan',
61
+ 'SessionManager',
62
+ 'SessionPanel',
63
+ 'SessionPersistence',
64
+ 'SessionState',
65
+ 'SettingsPanel',
66
+ 'StorageDb',
67
+ 'StorageKeys',
68
+ 'StorageMigration',
69
+ 'Summary',
70
+ 'Theme',
71
+ 'UndoOperations',
72
+ 'UpdateIdle',
73
+ 'UpdateNotice',
74
+ 'WritebackController',
75
+ 'WritebackOrchestrator',
76
+ 'WritebackSettlement'
77
+ ]);
78
+
79
+ const SUPPORT_MODULES = Object.freeze([
80
+ 'CompileAdapter',
81
+ 'MarkdownDomRenderer',
82
+ 'MathText',
83
+ 'ModelPickerSupport',
84
+ 'ProjectSessionCleanup',
85
+ 'ProviderProfiles',
86
+ 'ProviderSettingsDialog',
87
+ 'RunGuidanceView',
88
+ 'SessionMenuView'
89
+ ]);
90
+
91
+ function create(root) {
92
+ if (!root || typeof root !== 'object') {
93
+ throw new TypeError('Codex Overleaf content startup requires a browser global.');
94
+ }
95
+ const modules = {};
96
+ const missing = [];
97
+ for (const name of [...REQUIRED_MODULES, ...SUPPORT_MODULES]) {
98
+ const value = root[`CodexOverleaf${name}`];
99
+ if (!value) {
100
+ missing.push(`CodexOverleaf${name}`);
101
+ } else {
102
+ modules[name] = value;
103
+ }
104
+ }
105
+ if (missing.length) {
106
+ const error = new Error(`Codex Overleaf content dependencies are missing: ${missing.join(', ')}`);
107
+ error.code = 'content_dependency_missing';
108
+ error.missing = missing;
109
+ throw error;
110
+ }
111
+ const vendor = Object.freeze({
112
+ katex: root.katex || null,
113
+ markdownit: root.markdownit || null
114
+ });
115
+ return Object.freeze({
116
+ root,
117
+ chromeApi: root.chrome,
118
+ document: root.document,
119
+ modules: Object.freeze(modules),
120
+ vendor
121
+ });
122
+ }
123
+
124
+ return Object.freeze({
125
+ create,
126
+ requiredModules: REQUIRED_MODULES,
127
+ supportModules: SUPPORT_MODULES
128
+ });
129
+ });
@@ -1,8 +1,6 @@
1
1
  (function initCodexOverleafMarkdownText() {
2
2
  'use strict';
3
3
 
4
- const LineReferences = window.CodexOverleafLineReferences;
5
-
6
4
  // Markdown / assistant-text rendering — block + inline markdown, the
7
5
  // assistant-visible sanitizers, and line-reference resolution/buttons carved
8
6
  // out of contentRuntime.js (v1.4.5 structural-debt phase 1). The code below
@@ -10,15 +8,19 @@
10
8
  // are factory-injected so behavior is unchanged.
11
9
  function create(deps = {}) {
12
10
  const {
11
+ LineReferences,
12
+ MathText,
13
13
  tx,
14
- callPageBridge,
14
+ callPageBridge, getCurrentProjectId,
15
15
  getCurrentProjectReferenceFiles,
16
+ getCurrentProjectMathSources,
16
17
  showPluginToast
17
18
  } = deps;
18
19
 
19
20
  function renderMarkdownInlineText(target, value) {
20
21
  target.replaceChildren(...buildMarkdownInlineNodes(value));
21
22
  }
23
+ function getMathMacros() { return MathText?.buildMathMacros?.(getCurrentProjectMathSources?.() || []) || {}; }
22
24
 
23
25
  function sanitizeAssistantVisibleText(value) {
24
26
  if (typeof value !== 'string' || !value) {
@@ -63,17 +65,12 @@
63
65
 
64
66
  function buildMarkdownInlineNodes(value) {
65
67
  const source = String(value || '');
66
- const mathText = typeof window !== 'undefined'
67
- ? window.CodexOverleafMathText
68
- : null;
68
+ const mathText = MathText;
69
69
  if (!mathText?.buildMathNodes) {
70
70
  return buildMarkdownInlineNodesWithoutMath(source);
71
71
  }
72
- return mathText.buildMathNodes(source, {
73
- document,
74
- katex: window.katex,
75
- renderText: buildMarkdownInlineNodesWithoutMath
76
- });
72
+ return mathText.buildMathNodes(source, { document, katex: window.katex,
73
+ macros: getMathMacros(), renderText: buildMarkdownInlineNodesWithoutMath });
77
74
  }
78
75
 
79
76
  function buildMarkdownInlineNodesWithoutMath(value) {
@@ -111,6 +108,10 @@
111
108
  function buildInlineCodeNodes(value) {
112
109
  const source = String(value || '');
113
110
  const trimmed = source.trim();
111
+ const standaloneMath = MathText?.parseStandaloneMath?.(trimmed);
112
+ if (standaloneMath && MathText?.createMathNode) return [MathText.createMathNode(
113
+ standaloneMath, { document, katex: window.katex, macros: getMathMacros() }
114
+ )];
114
115
  const refs = trimmed ? parseRuntimeLineReferences(trimmed, 'plain-text-token') : [];
115
116
  const ref = refs.length === 1 && refs[0]?.rawText === trimmed ? refs[0] : null;
116
117
  if (ref && !isRuntimeLocalPathLike(ref.rawPath)) {
@@ -287,7 +288,7 @@
287
288
  button.disabled = true;
288
289
  button.dataset.status = 'pending';
289
290
  try {
290
- const result = await callPageBridge('jumpToPosition', params);
291
+ const result = await callPageBridge('jumpToPosition', { ...params, runProjectId: getCurrentProjectId?.() || '' });
291
292
  if (result?.ok === false) {
292
293
  button.dataset.status = 'failed';
293
294
  button.title = tx('Could not open that referenced line.', '无法打开引用的行。');
@@ -494,12 +495,11 @@
494
495
  `[${safeLabel.replace(/]/g, '\\]')}](${target.replace(/\)/g, '\\)')})`
495
496
  );
496
497
  },
497
- renderCodeNodes: text => buildMarkdownInlineNodes(`\`${String(text || '').replace(/`/g, '\\`')}\``),
498
+ renderCodeNodes: text => buildInlineCodeNodes(text),
498
499
  sanitizeText: sanitizeAssistantVisibleText,
499
- createMathNode: segment => runtimeRoot.CodexOverleafMathText.createMathNode(segment, {
500
- document, katex: runtimeRoot.katex,
501
- renderText: text => buildMarkdownInlineNodes(text)
502
- }),
500
+ createMathNode: segment => runtimeRoot.CodexOverleafMathText.createMathNode(segment,
501
+ { document, katex: runtimeRoot.katex, macros: getMathMacros(),
502
+ renderText: text => buildMarkdownInlineNodes(text) }),
503
503
  recordDiagnostic: recordRenderingDiagnostic
504
504
  });
505
505
  return;
@@ -9,6 +9,19 @@
9
9
  ]);
10
10
  const LONG_INLINE_MATH_CHARS = 120;
11
11
  const COMPLEX_INLINE_MATH_CHARS = 80;
12
+ const MAX_PROJECT_MACRO_SOURCES = 12;
13
+ const MAX_PROJECT_MACRO_SOURCE_CHARS = 256 * 1024;
14
+ const MAX_PROJECT_MACROS = 64;
15
+ const MAX_MACRO_EXPANSION_CHARS = 512;
16
+ const DEFAULT_MATH_MACROS = Object.freeze({
17
+ '\\E': '\\mathbb{E}',
18
+ '\\Var': '\\operatorname{Var}',
19
+ '\\Cov': '\\operatorname{Cov}',
20
+ '\\R': '\\mathbb{R}',
21
+ '\\N': '\\mathbb{N}',
22
+ '\\Z': '\\mathbb{Z}'
23
+ });
24
+ const UNSAFE_MACRO_PATTERN = /\\(?:href|url|includegraphics|input|include|write|openout|read|html\w*|class|style|data|def|gdef|edef|xdef|newcommand|renewcommand|providecommand|DeclareMathOperator)\b/i;
12
25
 
13
26
  function parseMathSegments(value) {
14
27
  const source = String(value || '');
@@ -74,9 +87,10 @@
74
87
  searchFrom = start + delimiter.open.length;
75
88
  continue;
76
89
  }
77
- const value = source.slice(start + delimiter.open.length, closeStart);
90
+ const rawValue = source.slice(start + delimiter.open.length, closeStart);
91
+ const value = rawValue.trim();
78
92
  const end = closeStart + delimiter.close.length;
79
- if (!isValidMathValue(value, delimiter) || overlapsCodeRange(start, end, codeRanges)) {
93
+ if (!isValidMathValue(rawValue, delimiter) || overlapsCodeRange(start, end, codeRanges)) {
80
94
  searchFrom = start + delimiter.open.length;
81
95
  continue;
82
96
  }
@@ -94,7 +108,7 @@
94
108
  }
95
109
  const previous = source[index - 1] || '';
96
110
  const next = source[index + 1] || '';
97
- return previous !== '$' && next !== '$' && next !== '' && !/\s/.test(next);
111
+ return previous !== '$' && next !== '$' && next !== '';
98
112
  }
99
113
 
100
114
  function findClosingDelimiter(source, fromIndex, delimiter, codeRanges) {
@@ -107,7 +121,7 @@
107
121
  const previous = source[index - 1] || '';
108
122
  const next = source[index + delimiter.close.length] || '';
109
123
  const invalidSingleDollar = delimiter.singleDollar
110
- && (previous === '$' || next === '$' || /\s/.test(previous));
124
+ && (previous === '$' || next === '$');
111
125
  if (!isEscaped(source, index) && !isInsideRange(index, codeRanges) && !invalidSingleDollar) {
112
126
  return index;
113
127
  }
@@ -118,10 +132,24 @@
118
132
 
119
133
  function isValidMathValue(value, delimiter) {
120
134
  const source = String(value || '');
121
- if (!source.trim()) {
135
+ const trimmed = source.trim();
136
+ if (!trimmed) {
122
137
  return false;
123
138
  }
124
- return delimiter.display || !/[\r\n]/.test(source);
139
+ if (!delimiter.display && /[\r\n]/.test(source)) {
140
+ return false;
141
+ }
142
+ if (!delimiter.singleDollar || (!/^\s/.test(source) && !/\s$/.test(source))) {
143
+ return true;
144
+ }
145
+ return looksLikeWhitespaceWrappedMath(trimmed);
146
+ }
147
+
148
+ function looksLikeWhitespaceWrappedMath(value) {
149
+ const source = String(value || '').trim();
150
+ return /\\[A-Za-z]+/.test(source)
151
+ || /[_^=<>+\-*/()[\]{}|]/.test(source)
152
+ || /^[A-Za-z](?:_[A-Za-z0-9{}]+|\^[A-Za-z0-9{}]+)?$/.test(source);
125
153
  }
126
154
 
127
155
  function collectInlineCodeRanges(source) {
@@ -179,7 +207,8 @@
179
207
  }
180
208
  nodes.push(createMathNode(segment, {
181
209
  document: documentRef,
182
- katex: options.katex || root.katex
210
+ katex: options.katex || root.katex,
211
+ macros: options.macros || buildMathMacros(options.projectSources)
183
212
  }));
184
213
  }
185
214
  return nodes;
@@ -206,6 +235,7 @@
206
235
  strict: 'warn',
207
236
  maxExpand: 200,
208
237
  maxSize: 20,
238
+ macros: options.macros || buildMathMacros(),
209
239
  output: 'htmlAndMathml'
210
240
  });
211
241
  node.dataset.mathRendered = 'true';
@@ -213,7 +243,7 @@
213
243
  } catch (_error) {
214
244
  node.classList.add('run-math--fallback');
215
245
  node.dataset.mathRendered = 'false';
216
- node.textContent = segment.raw;
246
+ node.textContent = source;
217
247
  return node;
218
248
  }
219
249
  }
@@ -235,6 +265,120 @@
235
265
  return /(?:=|\\(?:le|ge|approx|sim|to|Rightarrow|Longrightarrow)\b|\\begin\{(?:aligned|gathered|split|array)\}|\\\\)/.test(source);
236
266
  }
237
267
 
268
+ function parseStandaloneMath(value) {
269
+ const source = String(value || '').trim();
270
+ if (!source) {
271
+ return null;
272
+ }
273
+ const segments = parseMathSegments(source);
274
+ if (segments.length !== 1 || segments[0].type !== 'math' || segments[0].raw !== source) {
275
+ return null;
276
+ }
277
+ return segments[0];
278
+ }
279
+
280
+ function buildMathMacros(projectSources = []) {
281
+ const macros = { ...DEFAULT_MATH_MACROS };
282
+ let remainingChars = MAX_PROJECT_MACRO_SOURCE_CHARS;
283
+ let projectMacroCount = 0;
284
+ for (const sourceRecord of Array.isArray(projectSources)
285
+ ? projectSources.slice(0, MAX_PROJECT_MACRO_SOURCES)
286
+ : []) {
287
+ if (projectMacroCount >= MAX_PROJECT_MACROS || remainingChars <= 0) {
288
+ break;
289
+ }
290
+ const path = String(sourceRecord?.path || '');
291
+ if (!/\.(?:tex|sty|cls|ltx)$/i.test(path)) {
292
+ continue;
293
+ }
294
+ const source = stripLatexComments(
295
+ String(sourceRecord?.content || '').slice(0, remainingChars)
296
+ );
297
+ remainingChars -= source.length;
298
+ const pattern = /\\(newcommand|renewcommand|providecommand|DeclareMathOperator)(\*)?/g;
299
+ let match;
300
+ while ((match = pattern.exec(source)) !== null && projectMacroCount < MAX_PROJECT_MACROS) {
301
+ let cursor = skipWhitespace(source, pattern.lastIndex);
302
+ const nameGroup = readBracedGroup(source, cursor);
303
+ if (!nameGroup) {
304
+ continue;
305
+ }
306
+ const macroName = nameGroup.value.trim();
307
+ cursor = skipWhitespace(source, nameGroup.end);
308
+ if (source[cursor] === '[') {
309
+ continue;
310
+ }
311
+ const expansionGroup = readBracedGroup(source, cursor);
312
+ if (!expansionGroup) {
313
+ continue;
314
+ }
315
+ let expansion = expansionGroup.value.trim();
316
+ if (match[1] === 'DeclareMathOperator') {
317
+ expansion = `\\operatorname${match[2] ? '*' : ''}{${expansion}}`;
318
+ }
319
+ if (!isSafeMacroDefinition(macroName, expansion)) {
320
+ continue;
321
+ }
322
+ macros[macroName] = expansion;
323
+ projectMacroCount++;
324
+ pattern.lastIndex = expansionGroup.end;
325
+ }
326
+ }
327
+ return macros;
328
+ }
329
+
330
+ function readBracedGroup(source, start) {
331
+ if (source[start] !== '{') {
332
+ return null;
333
+ }
334
+ let depth = 0;
335
+ for (let index = start; index < source.length; index++) {
336
+ if (source[index] === '{' && !isEscaped(source, index)) {
337
+ depth++;
338
+ } else if (source[index] === '}' && !isEscaped(source, index)) {
339
+ depth--;
340
+ if (depth === 0) {
341
+ return {
342
+ value: source.slice(start + 1, index),
343
+ end: index + 1
344
+ };
345
+ }
346
+ }
347
+ }
348
+ return null;
349
+ }
350
+
351
+ function skipWhitespace(source, start) {
352
+ let index = start;
353
+ while (index < source.length && /\s/.test(source[index])) {
354
+ index++;
355
+ }
356
+ return index;
357
+ }
358
+
359
+ function stripLatexComments(source) {
360
+ return String(source || '').split(/\r?\n/).map(line => {
361
+ for (let index = 0; index < line.length; index++) {
362
+ if (line[index] === '%' && !isEscaped(line, index)) {
363
+ return line.slice(0, index);
364
+ }
365
+ }
366
+ return line;
367
+ }).join('\n');
368
+ }
369
+
370
+ function isSafeMacroDefinition(name, expansion) {
371
+ const macroName = String(name || '');
372
+ const body = String(expansion || '');
373
+ return /^\\[A-Za-z@]+$/.test(macroName)
374
+ && body.length > 0
375
+ && body.length <= MAX_MACRO_EXPANSION_CHARS
376
+ && !body.includes('#')
377
+ && !body.includes(macroName)
378
+ && !UNSAFE_MACRO_PATTERN.test(macroName)
379
+ && !UNSAFE_MACRO_PATTERN.test(body);
380
+ }
381
+
238
382
  function toNodeArray(value) {
239
383
  if (Array.isArray(value)) {
240
384
  return value;
@@ -265,11 +409,13 @@
265
409
  }
266
410
 
267
411
  const api = {
412
+ buildMathMacros,
268
413
  buildMathNodes,
269
414
  createMathNode,
270
415
  matchMathAt,
271
416
  normalizeMathForRendering,
272
- parseMathSegments
417
+ parseMathSegments,
418
+ parseStandaloneMath
273
419
  };
274
420
  root.CodexOverleafMathText = api;
275
421
  if (typeof module !== 'undefined' && module.exports) {
@@ -24,7 +24,7 @@
24
24
  getPanel,
25
25
  getState
26
26
  } = deps;
27
- const Support = window.CodexOverleafModelPickerSupport;
27
+ const Support = deps.Support;
28
28
  const {
29
29
  formatCompactModelLabel,
30
30
  normalizeModelOptionId,
@@ -1,4 +1,10 @@
1
- (function initCodexOverleafModelPickerSupport(root) {
1
+ (function initCodexOverleafModelPickerSupport(root, factory) {
2
+ if (typeof module === 'object' && module.exports) {
3
+ module.exports = factory(require('../shared/models'));
4
+ } else {
5
+ root.CodexOverleafModuleRegistry.define('ModelPickerSupport', ['Models'], factory);
6
+ }
7
+ })(typeof window !== 'undefined' ? window : globalThis, function modelPickerSupportFactory(Models) {
2
8
  'use strict';
3
9
 
4
10
  function normalizeModelOptionId(id) {
@@ -37,7 +43,7 @@
37
43
  }
38
44
 
39
45
  function getModelCatalog({ getPanel } = {}) {
40
- const shared = root.CodexOverleafModels;
46
+ const shared = Models;
41
47
  if (Array.isArray(shared?.FALLBACK_MODELS) && typeof shared?.normalizeDiscoveredModels === 'function') {
42
48
  return shared;
43
49
  }
@@ -110,6 +116,5 @@
110
116
  retainSelectedModel,
111
117
  shouldUseBuiltInFallback
112
118
  };
113
- root.CodexOverleafModelPickerSupport = api;
114
- if (typeof module === 'object' && module.exports) module.exports = api;
115
- })(typeof window !== 'undefined' ? window : globalThis);
119
+ return api;
120
+ });