-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathoffscreen.js
More file actions
236 lines (198 loc) · 7.38 KB
/
offscreen.js
File metadata and controls
236 lines (198 loc) · 7.38 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
// offscreen.js - Handles WASM execution in offscreen document
// Offscreen documents can load WASM without CSP issues
let modulePromise = null;
let lastMessage = "";
let lastError = "";
// Load WASM module
async function getModule() {
if (!modulePromise) {
modulePromise = new Promise(async (resolve, reject) => {
try {
console.log('🔧 Loading WASM in offscreen document...');
// Load the WASM JS glue code
const script = document.createElement('script');
script.src = chrome.runtime.getURL('wasm/citeorder.js');
script.onload = async () => {
console.log('✓ citeorder.js loaded');
if (typeof CiteorderModule !== 'function') {
throw new Error('CiteorderModule not found');
}
try {
const Module = await CiteorderModule({
locateFile: (path) => chrome.runtime.getURL('wasm/' + path),
print: (text) => {
if (!text.includes("Output written to")) {
lastMessage = text;
}
console.log('citeorder:', text);
},
printErr: (text) => {
lastError = text;
// console.warn('citeorder:', text);
},
noInitialRun: true // Don't call main() on startup!
});
console.log('✅ WASM module loaded');
resolve(Module);
} catch (err) {
console.error('❌ WASM init failed:', err);
reject(err);
}
};
script.onerror = () => {
reject(new Error('Failed to load citeorder.js'));
};
document.head.appendChild(script);
} catch (error) {
console.error('❌ Load error:', error);
reject(error);
}
});
}
return modulePromise;
}
// Process markdown with citeorder CLI
async function processCiteorder(text, flags) {
lastMessage = "";
lastError = "";
try {
const Module = await getModule();
const FS = Module.FS;
// Setup virtual filesystem
const inputFile = '/input.md';
const outputFile = '/input-fixed.md';
// Normalize line endings to \n (Unix style) before processing
const normalizedText = text.replace(/\r\n/g, '\n').replace(/\r/g, '\n');
console.log('📝 Normalized:', text.length, '→', normalizedText.length, 'bytes');
// Write input
FS.writeFile(inputFile, normalizedText);
// FS.writeFile(inputFile, text);
console.log('📝 Wrote', normalizedText.length, 'bytes to', inputFile);
console.log('📝 First 200 chars:', normalizedText.substring(0, 200));
const lineCount = normalizedText.split('\n').length;
console.log('📝 Line count:', lineCount);
// console.log('📝 Wrote', text.length, 'bytes to', inputFile);
// console.log('📝 First 200 chars:', text.substring(0, 200));
// console.log('📝 Line count:', text.split('\n').length);
// Line-count guard
if (lineCount > 5000) {
const message = `File too large (${lineCount} lines). citeorder currently supports up to 5000 lines.`;
chrome.runtime.sendMessage({
type: "citeorder-status",
status: "error",
message: message
});
return {
result: null,
error: message,
aborted: true
};
}
// Verify file exists
try {
const stat = FS.stat(inputFile);
console.log('✓ File exists, size:', stat.size);
// Try to read it back to verify
const readback = FS.readFile(inputFile, { encoding: 'utf8' });
console.log('✓ Readback successful, length:', readback.length);
console.log('✓ File matches:', readback === text);
} catch (e) {
console.error('❌ File not found after write:', e);
}
// Build arguments
const args = [];
if (flags.q) args.push('-q');
if (flags.d) args.push('-d');
args.push(inputFile);
console.log('🔧 Command:', 'citeorder', args.join(' '));
console.log('🔧 Args array:', args);
console.log('🔧 Args contents:', JSON.stringify(args));
// Capture stdout/stderr
let stdout = '';
let stderr = '';
// Module.print = (t) => { stdout += t + '\n'; };
// Module.printErr = (t) => { stderr += t + '\n'; };
// Run CLI
// callMain adds argv[0] automatically, so only pass actual arguments
console.log('▶️ Calling main with args:', args);
let exitStatus = 0;
try {
const returnCode = Module.callMain(args);
console.log('✓ callMain completed with return code:', returnCode);
exitStatus = returnCode;
} catch (e) {
console.log('⚠️ callMain threw:', e, 'status:', e.status);
// Emscripten throws on exit() - capture the status
if (e === 'ExitStatus') {
exitStatus = 0; // Normal exit
} else if (typeof e.status === 'number') {
exitStatus = e.status; // Error exit
console.log('❌ Program exited with status:', exitStatus);
} else {
throw e; // Unexpected error
}
}
// send stdout/stderr to content.js
if (lastError) {
chrome.runtime.sendMessage({
type: "citeorder-status",
status: "error",
message: lastError
});
} else if (lastMessage) {
chrome.runtime.sendMessage({
type: "citeorder-status",
status: "ok",
message: lastMessage
});
}
// Read output
let result = null;
console.log('📤 Checking for output file...');
console.log('📤 Exit status:', exitStatus);
console.log('📤 stdout:', stdout);
console.log('📤 stderr:', stderr);
// If exit status is non-zero, the program failed
if (exitStatus !== 0) {
const output = (stdout + stderr).trim();
throw new Error(output || 'Program exited with error status ' + exitStatus);
}
try {
result = FS.readFile(outputFile, { encoding: 'utf8' });
console.log('✓ Read output file, length:', result.length);
// Cleanup
try {
FS.unlink(inputFile);
FS.unlink(outputFile);
} catch (e) {
// Ignore cleanup errors
}
} catch (e) {
console.log('⚠️ No output file:', e.message);
// No output file - check for "No changes required"
const output = (stdout + stderr).trim();
console.log('📋 Combined output:', output);
if (output.includes('No changes required') || output.includes('no changes')) {
return { result: null, message: 'No changes required', stdout, stderr };
}
throw new Error(output || e.message);
}
return { result, stdout, stderr };
} catch (error) {
throw new Error('Processing failed: ' + error.message);
}
}
// Listen for messages from background script
chrome.runtime.onMessage.addListener((request, sender, sendResponse) => {
if (request.type === 'PROCESS_CITEORDER') {
processCiteorder(request.text, request.flags)
.then(result => {
sendResponse({ success: true, ...result });
})
.catch(error => {
sendResponse({ success: false, error: error.message });
});
return true; // Async response
}
});
console.log('🚀 Citeorder offscreen document ready');