@yeyuan98/opencode-bioresearcher-plugin 1.7.1-alpha.0 → 1.7.2

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.
@@ -25,6 +25,228 @@ th { background: #f6f8fa; font-weight: 600; }
25
25
  tr:nth-child(even) { background: #f6f8fa; }
26
26
  hr { border: none; border-top: 1px solid #d0d7de; margin: 2em 0; }
27
27
  img { max-width: 100%; border-radius: 6px; }
28
+ .cite-ref { font-size: 0.75em; vertical-align: super; line-height: 0; }
29
+ .cite-ref a { color: #0969da; cursor: pointer; text-decoration: none; font-weight: 600; padding: 0 0.1em; }
30
+ .cite-ref a:hover { text-decoration: underline; }
31
+ .cite-tooltip { position: absolute; z-index: 9999; max-width: 420px; min-width: 260px; padding: 12px 16px; background: #fff; border: 1px solid #d0d7de; border-radius: 8px; box-shadow: 0 8px 24px rgba(0,0,0,0.12); font-size: 13px; line-height: 1.5; color: #24292f; display: none; opacity: 0; transition: opacity 0.15s ease-in-out; }
32
+ .cite-tooltip.visible { display: block; }
33
+ .cite-tooltip.fade-in { opacity: 1; }
34
+ .cite-tooltip.fade-out { opacity: 0; }
35
+ .cite-tooltip .cite-label { font-size: 11px; color: #656d76; margin-bottom: 6px; text-transform: uppercase; letter-spacing: 0.05em; }
36
+ .cite-tail { position: absolute; top: -6px; left: 50%; transform: translateX(-50%); width: 0; height: 0; border-left: 6px solid transparent; border-right: 6px solid transparent; border-bottom: 6px solid #d0d7de; }
37
+ .cite-tail::after { content: ''; position: absolute; top: 1px; left: -5px; width: 0; height: 0; border-left: 5px solid transparent; border-right: 5px solid transparent; border-bottom: 5px solid #fff; }
38
+ .cite-tail.flip { top: auto; bottom: -6px; border-bottom: none; border-top: 6px solid #d0d7de; }
39
+ .cite-tail.flip::after { top: auto; bottom: 1px; border-bottom: none; border-top: 5px solid #fff; }
40
+ .cite-tooltip a.ref-link { color: #0969da; text-decoration: none; }
41
+ .cite-tooltip a.ref-link:hover { text-decoration: underline; }
42
+ `.trim();
43
+ const CITATION_POSTPROCESS_JS = `
44
+ (function() {
45
+ var c = document.getElementById('content');
46
+ if (!c) return;
47
+ var hs = c.querySelectorAll('h1,h2,h3,h4,h5,h6');
48
+ var rh = null;
49
+ for (var i = 0; i < hs.length; i++) {
50
+ if (/^references?$/i.test(hs[i].textContent.trim())) { rh = hs[i]; break; }
51
+ }
52
+ if (!rh) return;
53
+ var re = new Set();
54
+ re.add(rh);
55
+ var el = rh.nextElementSibling;
56
+ while (el) {
57
+ if (/^H[1-6]$/i.test(el.tagName)) break;
58
+ re.add(el);
59
+ el = el.nextElementSibling;
60
+ }
61
+ var refs = new Map();
62
+ function extractRefs(node) {
63
+ var items = (node.tagName === 'OL' || node.tagName === 'UL')
64
+ ? node.querySelectorAll('li') : [node];
65
+ for (var i = 0; i < items.length; i++) {
66
+ var t = items[i].textContent.trim();
67
+ var m = t.match(/^\\[(\\d+)\\]\\s*([\\s\\S]*)/);
68
+ if (m) refs.set(parseInt(m[1]), m[2].trim());
69
+ }
70
+ }
71
+ re.forEach(function(e) { if (e !== rh) extractRefs(e); });
72
+ if (refs.size === 0) return;
73
+ function inRef(n) {
74
+ var p = n.parentElement;
75
+ while (p && p !== c) { if (re.has(p)) return true; p = p.parentElement; }
76
+ return false;
77
+ }
78
+ function inCode(n) {
79
+ var p = n.parentElement;
80
+ while (p && p !== c) {
81
+ if (p.tagName === 'CODE' || p.tagName === 'PRE') return true;
82
+ p = p.parentElement;
83
+ }
84
+ return false;
85
+ }
86
+ var w = document.createTreeWalker(c, NodeFilter.SHOW_TEXT);
87
+ var nodes = [];
88
+ while (w.nextNode()) nodes.push(w.currentNode);
89
+ var regex = /\\[(\\d+(?:\\s*[,,]\\s*\\d+)*(?:\\s*[-–]\\s*\\d+)?)\\]/g;
90
+ for (var i = 0; i < nodes.length; i++) {
91
+ var node = nodes[i];
92
+ if (inRef(node) || inCode(node)) continue;
93
+ var text = node.textContent;
94
+ if (!regex.test(text)) continue;
95
+ regex.lastIndex = 0;
96
+ var frag = document.createDocumentFragment();
97
+ var li = 0, m;
98
+ while ((m = regex.exec(text)) !== null) {
99
+ if (m.index > li)
100
+ frag.appendChild(document.createTextNode(text.slice(li, m.index)));
101
+ var nums = [];
102
+ m[1].split(/[,,]/).forEach(function(p) {
103
+ p = p.trim();
104
+ var rm = p.match(/^(\\d+)\\s*[-–]\\s*(\\d+)$/);
105
+ if (rm) {
106
+ for (var j = parseInt(rm[1]); j <= parseInt(rm[2]); j++) nums.push(j);
107
+ } else {
108
+ var n = parseInt(p);
109
+ if (!isNaN(n)) nums.push(n);
110
+ }
111
+ });
112
+ var sup = document.createElement('sup');
113
+ sup.className = 'cite-ref';
114
+ nums.forEach(function(num, idx) {
115
+ if (idx > 0) sup.appendChild(document.createTextNode(', '));
116
+ var a = document.createElement('a');
117
+ a.textContent = num;
118
+ a.setAttribute('data-ref', num);
119
+ a.href = '#ref-' + num;
120
+ sup.appendChild(a);
121
+ });
122
+ frag.appendChild(sup);
123
+ li = regex.lastIndex;
124
+ }
125
+ if (li < text.length)
126
+ frag.appendChild(document.createTextNode(text.slice(li)));
127
+ node.parentNode.replaceChild(frag, node);
128
+ }
129
+ re.forEach(function(e) {
130
+ if (e === rh) return;
131
+ var items = (e.tagName === 'OL' || e.tagName === 'UL')
132
+ ? e.querySelectorAll('li') : [e];
133
+ for (var i = 0; i < items.length; i++) {
134
+ var t = items[i].textContent.trim();
135
+ var m = t.match(/^\\[(\\d+)\\]/);
136
+ if (m) items[i].id = 'ref-' + m[1];
137
+ }
138
+ });
139
+ function esc(s) {
140
+ return s.replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;');
141
+ }
142
+ function linkify(s) {
143
+ var ph = [];
144
+ function phPush(html) { var i = ph.length; ph.push(html); return '%%PH' + i + '%%'; }
145
+ s = s.replace(/\\bdoi:\\s*(10\\.\\d{4,9}\\/\\S*[^\\s.,;:])/gi, function(_, doi) {
146
+ return phPush('<a class="ref-link" href="https://doi.org/' + esc(doi) + '" target="_blank" rel="noopener">doi:' + esc(doi) + '<\\/a>');
147
+ });
148
+ s = s.replace(/\\bPMID:\\s*(\\d+)/gi, function(_, id) {
149
+ return phPush('<a class="ref-link" href="https://pubmed.ncbi.nlm.nih.gov/' + id + '/" target="_blank" rel="noopener">PMID: ' + id + '<\\/a>');
150
+ });
151
+ var parts = s.split(/(https?:\\/\\/[^\\s<>"]+)/g);
152
+ return parts.map(function(p, i) {
153
+ if (i % 2 === 1) return '<a class="ref-link" href="' + esc(p) + '" target="_blank" rel="noopener">' + esc(p) + '<\\/a>';
154
+ return esc(p).replace(/%%PH(\\d+)%%/g, function(_, idx) { return ph[parseInt(idx)]; });
155
+ }).join('');
156
+ }
157
+ refs.forEach(function(text, num) {
158
+ var tt = document.createElement('div');
159
+ tt.className = 'cite-tooltip';
160
+ tt.id = 'cite-tooltip-' + num;
161
+ tt.innerHTML = '<div class="cite-tail"><\\/div><div class="cite-label">Reference [' + num + ']<\\/div><div>' + linkify(text) + '<\\/div>';
162
+ document.body.appendChild(tt);
163
+ });
164
+ var active = null, st = null, ht = null, hat = null;
165
+ function showTooltip(a) {
166
+ clearTimeout(hat); hat = null;
167
+ var n = a.getAttribute('data-ref');
168
+ var tt = document.getElementById('cite-tooltip-' + n);
169
+ if (!tt) return;
170
+ hideCurrent();
171
+ var r = a.getBoundingClientRect();
172
+ var sy = window.scrollY || document.documentElement.scrollTop;
173
+ var sx = window.scrollX || document.documentElement.scrollLeft;
174
+ tt.style.left = '0px';
175
+ tt.style.top = '0px';
176
+ tt.classList.add('visible');
177
+ tt.classList.remove('fade-out');
178
+ var tr = tt.getBoundingClientRect();
179
+ var l = r.left + sx + r.width / 2 - tr.width / 2;
180
+ var t = r.bottom + sy + 6;
181
+ if (l < 8) l = 8;
182
+ if (l + tr.width > window.innerWidth - 8) l = window.innerWidth - tr.width - 8;
183
+ if (t + tr.height > window.innerHeight + sy - 8) t = r.top + sy - tr.height - 6;
184
+ var above = t < r.top + sy;
185
+ var tail = tt.querySelector('.cite-tail');
186
+ if (tail) {
187
+ var tailL = (r.left + sx + r.width / 2) - l;
188
+ tail.style.left = tailL + 'px';
189
+ tail.style.transform = 'none';
190
+ if (above) tail.classList.add('flip'); else tail.classList.remove('flip');
191
+ }
192
+ tt.style.left = l + 'px';
193
+ tt.style.top = t + 'px';
194
+ requestAnimationFrame(function() { tt.classList.add('fade-in'); });
195
+ active = tt;
196
+ }
197
+ function hideCurrent() {
198
+ if (!active) return;
199
+ var prev = active;
200
+ prev.classList.remove('fade-in');
201
+ prev.classList.add('fade-out');
202
+ hat = setTimeout(function() {
203
+ prev.classList.remove('visible', 'fade-out');
204
+ }, 150);
205
+ if (active === prev) active = null;
206
+ }
207
+ function scheduleHide() {
208
+ ht = setTimeout(function() { hideCurrent(); }, 200);
209
+ }
210
+ function cancelHide() {
211
+ clearTimeout(ht);
212
+ ht = null;
213
+ clearTimeout(hat);
214
+ hat = null;
215
+ }
216
+ document.addEventListener('mouseenter', function(e) {
217
+ var a = e.target.closest('.cite-ref a');
218
+ if (!a) return;
219
+ cancelHide();
220
+ clearTimeout(st);
221
+ st = setTimeout(function() { showTooltip(a); }, 300);
222
+ }, true);
223
+ document.addEventListener('mouseleave', function(e) {
224
+ var a = e.target.closest('.cite-ref a');
225
+ if (!a) return;
226
+ clearTimeout(st);
227
+ scheduleHide();
228
+ }, true);
229
+ document.addEventListener('mouseenter', function(e) {
230
+ if (e.target.closest('.cite-tooltip')) cancelHide();
231
+ }, true);
232
+ document.addEventListener('mouseleave', function(e) {
233
+ if (e.target.closest('.cite-tooltip')) scheduleHide();
234
+ }, true);
235
+ document.addEventListener('click', function(e) {
236
+ var a = e.target.closest('.cite-ref a');
237
+ if (!a) return;
238
+ e.preventDefault();
239
+ var n = a.getAttribute('data-ref');
240
+ var tt = document.getElementById('cite-tooltip-' + n);
241
+ if (!tt) return;
242
+ if (active === tt && tt.classList.contains('fade-in')) {
243
+ hideCurrent();
244
+ } else {
245
+ clearTimeout(st);
246
+ showTooltip(a);
247
+ }
248
+ });
249
+ })();
28
250
  `.trim();
29
251
  function buildHtml(markdown, title, extraCss) {
30
252
  const escapedMarkdown = JSON.stringify(markdown).replace(/<\//g, String.raw `<\/`);
@@ -42,6 +264,7 @@ function buildHtml(markdown, title, extraCss) {
42
264
  <div id="content"></div>
43
265
  <script>${MARKED_BUNDLE}</script>
44
266
  <script>document.getElementById('content').innerHTML = marked.parse(${escapedMarkdown});</script>
267
+ <script>${CITATION_POSTPROCESS_JS}</script>
45
268
  </body>
46
269
  </html>`;
47
270
  }
@@ -1,4 +1,6 @@
1
+ import * as fs from 'fs';
1
2
  import * as XLSX from '../../../vendor/xlsx.mjs';
3
+ XLSX.set_fs(fs);
2
4
  export function getText(obj) {
3
5
  if (obj === null || obj === undefined)
4
6
  return null;
@@ -0,0 +1,8 @@
1
+ export declare abstract class BaseTableBackend {
2
+ protected resolvedPath: string;
3
+ protected force: boolean;
4
+ constructor(resolvedPath: string, force: boolean);
5
+ abstract readonly type: string;
6
+ protected ensureSheetIndex(sheetIndex: number): void;
7
+ protected resolveSheetName(sheetName: string | undefined, availableNames: string[]): string;
8
+ }
@@ -0,0 +1,23 @@
1
+ import { checkFileSize } from '../utils';
2
+ export class BaseTableBackend {
3
+ resolvedPath;
4
+ force;
5
+ constructor(resolvedPath, force) {
6
+ this.resolvedPath = resolvedPath;
7
+ this.force = force;
8
+ checkFileSize(resolvedPath, force);
9
+ }
10
+ ensureSheetIndex(sheetIndex) {
11
+ if (sheetIndex !== 0) {
12
+ throw new Error('This file format only supports a single sheet (index 0)');
13
+ }
14
+ }
15
+ resolveSheetName(sheetName, availableNames) {
16
+ if (!sheetName)
17
+ return availableNames[0];
18
+ if (!availableNames.includes(sheetName)) {
19
+ throw new Error(`Sheet "${sheetName}" not found`);
20
+ }
21
+ return sheetName;
22
+ }
23
+ }
@@ -0,0 +1,64 @@
1
+ import { BaseTableBackend } from '../base';
2
+ import type { IWritableTableBackend, SheetInfo } from '../interface';
3
+ export declare class CSVBackend extends BaseTableBackend implements IWritableTableBackend {
4
+ readonly type = "csv";
5
+ private delimiter;
6
+ private _headers;
7
+ private _totalDataRows;
8
+ constructor(resolvedPath: string, force: boolean);
9
+ private readHeaders;
10
+ private countDataRows;
11
+ listSheets(): SheetInfo[];
12
+ getHeaders(sheetIndex: number): {
13
+ headers: string[];
14
+ columnCount: number;
15
+ };
16
+ getTotalDataRows(sheetIndex: number): number;
17
+ getCell(sheetIndex: number, cellAddress: string): {
18
+ value: any;
19
+ type: string;
20
+ };
21
+ getRange(sheetIndex: number, range: string): any;
22
+ getPreview(sheetIndex: number, maxRows: number): {
23
+ rows: any[][];
24
+ totalRows: number;
25
+ };
26
+ search(sheetIndex: number, searchTerm: string, options: {
27
+ column?: string;
28
+ maxResults: number;
29
+ maxRowsScan: number;
30
+ }): {
31
+ results: any[];
32
+ totalMatchesFound: number;
33
+ rowsScanned: number;
34
+ };
35
+ filterRows(sheetIndex: number, column: string, operator: string, value: any, options: {
36
+ maxResults: number;
37
+ maxRowsScan: number;
38
+ }): {
39
+ matchedRows: Record<string, any>[];
40
+ totalMatchesFound: number;
41
+ totalDataRows: number;
42
+ };
43
+ summarize(sheetIndex: number, columns: string[] | undefined, options: {
44
+ maxRowsScan: number;
45
+ }): {
46
+ summaries: Record<string, any>;
47
+ rowCount: number;
48
+ };
49
+ groupBy(sheetIndex: number, groupColumn: string, aggColumn: string, aggType: string, options: {
50
+ maxRowsScan: number;
51
+ }): {
52
+ groups: Record<string, number>;
53
+ };
54
+ pivotSummary(sheetIndex: number, rowField: string, colField: string, valueField: string, agg: string, options: {
55
+ maxRowsScan: number;
56
+ }): {
57
+ columns: string[];
58
+ pivot: Record<string, Record<string, number>>;
59
+ };
60
+ appendRows(sheetIndex: number, rows: any[]): void;
61
+ updateCell(sheetIndex: number, cellAddress: string, value: any): void;
62
+ createFile(sheetName: string, data: any): void;
63
+ dispose(): void;
64
+ }