@a9i5k4/dsh-literature 0.3.5 → 0.3.6

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/lib/index.js CHANGED
@@ -757,7 +757,7 @@ var UA, FetchFailure;
757
757
  var init_net = __esm({
758
758
  "src/node/net.js"() {
759
759
  init_log();
760
- UA = "dsh-literature/0.3.5 (+https://github.com/deepseek-ai/deepseek-harness)";
760
+ UA = "dsh-literature/0.3.6 (+https://github.com/deepseek-ai/deepseek-harness)";
761
761
  FetchFailure = class extends Error {
762
762
  constructor(message, { code = "network", status = 0, retryable = true, cause } = {}) {
763
763
  super(message, { cause });
@@ -2421,6 +2421,8 @@ function titleFromFilename(name2) {
2421
2421
  if (doi) return { kind: "doi", value: doi[1].replace(/_/g, "/") };
2422
2422
  const arxiv = /\b(\d{4}\.\d{4,5})(v\d+)?\b/.exec(t);
2423
2423
  if (arxiv) return { kind: "arxiv", value: arxiv[1] + (arxiv[2] ?? "") };
2424
+ const springer = /^([a-z]\d{4,6}-\d{2,4}-\d{2,6}(?:-[a-z0-9]{1,10})?)(?:\s*\(\d+\))?\s*$/i.exec(t.trim());
2425
+ if (springer) return { kind: "doi", value: `10.1007/${springer[1].toLowerCase()}` };
2424
2426
  t = t.replace(/^\[\d+\]\s*/, "").replace(/\s*\(?\d{4}[a-z]?\)?\s*$/i, "").replace(/[_\-]+/g, " ").replace(/^\d+[\s.]+/, "").trim();
2425
2427
  if (!t) return null;
2426
2428
  return { kind: "title", value: t };
@@ -2825,6 +2827,7 @@ __export(pipeline_exports, {
2825
2827
  log: () => log,
2826
2828
  normalizeDoi: () => normalizeDoi,
2827
2829
  previewConflict: () => previewConflict,
2830
+ reidentifyItem: () => reidentifyItem,
2828
2831
  resolveItem: () => resolveItem,
2829
2832
  retryItem: () => retryItem,
2830
2833
  saveItem: () => saveItem,
@@ -3275,6 +3278,33 @@ async function importDroppedPdf(buffer, { filename = "dropped.pdf" } = {}) {
3275
3278
  emitItem(saved);
3276
3279
  return saved;
3277
3280
  }
3281
+ async function reidentifyItem(key) {
3282
+ const item = await getItem(key);
3283
+ if (!item) throw failure("not_found", "\u6761\u76EE\u4E0D\u5B58\u5728");
3284
+ const name2 = item.pdf?.filename ?? item.sourceFile ?? (item.rawValue ? `${item.rawValue}.pdf` : "");
3285
+ const { titleFromFilename: titleFromFilename2 } = await Promise.resolve().then(() => (init_importer(), importer_exports));
3286
+ const hit = titleFromFilename2(name2);
3287
+ if (!hit || hit.kind === "title") {
3288
+ throw failure("network", "\u65E0\u6CD5\u4ECE\u6587\u4EF6\u540D\u8BC6\u522B\u51FA DOI / arXiv \u6807\u8BC6\u7B26\uFF0C\u8BF7\u624B\u52A8\u7C98\u8D34\u6807\u8BC6\u7B26\u540E\u91CD\u8BD5");
3289
+ }
3290
+ let next = await patchItem(key, {
3291
+ kind: hit.kind,
3292
+ rawValue: hit.value,
3293
+ display: hit.value,
3294
+ doi: hit.kind === "doi" ? hit.value : "",
3295
+ arxiv: hit.kind === "arxiv" ? hit.value : "",
3296
+ isbn: "",
3297
+ record: null,
3298
+ error: null
3299
+ });
3300
+ emitItem(next);
3301
+ try {
3302
+ next = await resolveItem(key);
3303
+ } catch {
3304
+ }
3305
+ emitItem(next);
3306
+ return next;
3307
+ }
3278
3308
  async function importDroppedCourseware(buffer, { filename = "deck.pptx" } = {}) {
3279
3309
  if (!buffer || buffer.length < 4 || buffer.subarray(0, 2).toString("latin1") !== "PK") {
3280
3310
  throw failure("network", "\u62D6\u5165\u7684\u6587\u4EF6\u4E0D\u662F\u6709\u6548\u7684 .pptx\uFF08\u65E7\u7248 .ppt \u8BF7\u5148\u53E6\u5B58\u4E3A .pptx \u6216\u5BFC\u51FA PDF\uFF09");
@@ -36262,7 +36292,7 @@ init_health();
36262
36292
  init_local_api();
36263
36293
  init_connector();
36264
36294
  init_log();
36265
- import { readFile as readFile5 } from "node:fs/promises";
36295
+ import { readFile as readFile5, open as openFile, stat as statFile } from "node:fs/promises";
36266
36296
  import { resolve as resolve5 } from "node:path";
36267
36297
  var PREFIX2 = "/api/dsh-literature";
36268
36298
  function pathOf(req) {
@@ -36311,30 +36341,44 @@ async function servePdf(req, res, key) {
36311
36341
  writeJson(res, 400, { error: "invalid key", code: "invalidKey" });
36312
36342
  return;
36313
36343
  }
36314
- let buffer;
36344
+ let size = 0;
36315
36345
  try {
36316
- buffer = await readFile5(path);
36346
+ size = (await statFile(path)).size;
36317
36347
  } catch {
36318
36348
  writeJson(res, 404, { error: "pdf not downloaded yet", code: "pdfNotDownloaded" });
36319
36349
  return;
36320
36350
  }
36321
- const range = parseRange(req.headers.range, buffer.length);
36351
+ const range = parseRange(req.headers.range, size);
36322
36352
  if (range?.invalid) {
36323
- res.writeHead(416, { "content-range": `bytes */${buffer.length}`, "content-length": 0 });
36353
+ res.writeHead(416, { "content-range": `bytes */${size}`, "content-length": 0 });
36324
36354
  res.end();
36325
36355
  return;
36326
36356
  }
36327
36357
  if (range) {
36328
- const slice = buffer.subarray(range.start, range.end + 1);
36358
+ const len = range.end - range.start + 1;
36359
+ const slice = Buffer.alloc(len);
36360
+ const fh = await openFile(path, "r");
36361
+ try {
36362
+ await fh.read(slice, 0, len, range.start);
36363
+ } finally {
36364
+ await fh.close();
36365
+ }
36329
36366
  res.writeHead(206, {
36330
36367
  "content-type": "application/pdf",
36331
36368
  "content-length": slice.length,
36332
- "content-range": `bytes ${range.start}-${range.end}/${buffer.length}`,
36369
+ "content-range": `bytes ${range.start}-${range.end}/${size}`,
36333
36370
  "accept-ranges": "bytes"
36334
36371
  });
36335
36372
  res.end(req.method === "HEAD" ? void 0 : slice);
36336
36373
  return;
36337
36374
  }
36375
+ let buffer;
36376
+ try {
36377
+ buffer = await readFile5(path);
36378
+ } catch {
36379
+ writeJson(res, 404, { error: "pdf not downloaded yet", code: "pdfNotDownloaded" });
36380
+ return;
36381
+ }
36338
36382
  res.writeHead(200, {
36339
36383
  "content-type": "application/pdf",
36340
36384
  "content-length": buffer.length,
@@ -36485,6 +36529,12 @@ async function handler(req, res, ctx2, { activation } = {}) {
36485
36529
  writeJson(res, 200, { item });
36486
36530
  return;
36487
36531
  }
36532
+ if (head === "reidentify" && methodOk(req, "POST")) {
36533
+ const body = await readJsonBody2(req);
36534
+ const item = await reidentifyItem(String(body?.key ?? ""));
36535
+ writeJson(res, 200, { item });
36536
+ return;
36537
+ }
36488
36538
  if (head === "save" && methodOk(req, "POST")) {
36489
36539
  const body = await readJsonBody2(req);
36490
36540
  const item = await saveItem(String(body?.key ?? ""), { mode: body?.mode, tags: body?.tags });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@a9i5k4/dsh-literature",
3
- "version": "0.3.5",
3
+ "version": "0.3.6",
4
4
  "description": "DSH Literature 文献侧窗:在 DeepSeek Harness 侧边栏识别 DOI/arXiv/标题、抓取元数据与全文、写入本地文献库或导出目录,并提供内置 PDF 阅读器(缩放/翻页/目录/搜索/高亮/笔记)。",
5
5
  "type": "module",
6
6
  "main": "lib/index.js",