Skip to content

chore: bump fig-extract to v2.7.0 - #25

Merged
onetwothr1 merged 2 commits into
devfrom
chore/bum-fig-extract-v2.7.0
Jul 16, 2026
Merged

chore: bump fig-extract to v2.7.0#25
onetwothr1 merged 2 commits into
devfrom
chore/bum-fig-extract-v2.7.0

Conversation

@onetwothr1

@onetwothr1 onetwothr1 commented Jul 16, 2026

Copy link
Copy Markdown
Collaborator

Summary

검증된 figure 추출 엔진 v2.7.0을 byte-identical vendoring합니다. 기존에는 Figure caption이 figure 하단에 있는 경우만 탐지했으나, 이제 상단에 있는 경우도 탐지합니다. 출력 계약과 TypeScript 타입은 변경되지 않습니다.

Changes

  • src/core/fig-extract.js를 v2.7.0으로 갱신
  • 통합 문서에 label-above 지원 및 side-caption 잔여 한계 반영

Test plan

  • npm run typecheck
  • npm test — 26 tests passed
  • npm run build
  • 원본/벤더 파일 SHA-256 일치 확인
  • Margin 그림·표 탭 스캔 및 프리뷰 수동 스모크 확인

Checklist

  • PR 제목이 Conventional Commits 형식 (chore: bump fig-extract to v2.7.0)
  • npm run typecheck · npm test 통과
  • AI-assisted

Summary by CodeRabbit

  • 개선 사항

    • 그림 추출 기능이 v2.7.0으로 업데이트되었습니다.
    • 그림 위에 짧게 표시되는 Figure N 라벨이 있는 레이아웃의 인식이 개선되었습니다.
    • 일반 그림 캡션뿐 아니라 Extended Data 및 보충 자료 캡션 인식이 강화되었습니다.
    • 그림 위치와 캡션 간 관계를 더 정확히 분석해 잘못된 그림 선택을 줄였습니다.
  • 문서

    • 라벨이 없는 그림과 좌·우 배치형 캡션의 지원 범위 및 제한 사항을 명확히 안내했습니다.

@onetwothr1
onetwothr1 requested a review from enu3379 as a code owner July 16, 2026 15:39
@coderabbitai

coderabbitai Bot commented Jul 16, 2026

Copy link
Copy Markdown

Review Change Stack

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 0fec66b0-ea95-4837-b1b7-4796ae8a33af

📥 Commits

Reviewing files that changed from the base of the PR and between bb335ea and d2a35c0.

📒 Files selected for processing (2)
  • docs/fig-extract-integration.md
  • src/core/fig-extract.js

📝 Walkthrough

Walkthrough

fig-extract 엔진이 v2.7.0으로 갱신되며 보충 캡션 인식, 상향·하향 figure 후보 생성, 점수 기반 후보 선택이 추가되었다. 문서는 label-above 지원과 side-caption 미지원 범위를 반영했다.

Changes

Figure extraction engine

Layer / File(s) Summary
캡션 인식 및 지원 범위
src/core/fig-extract.js, docs/fig-extract-integration.md
버전이 2.7.0으로 갱신되고 Figure/Fig 및 ED/S/Suppl 캡션 매칭이 통합되었다. 짧은 단독 label-above는 지원되며 side-caption은 미지원으로 문서화되었다.
상향 스캔 후보 평가
src/core/fig-extract.js
상향 스캔의 중단 사유, 경계 계산, 섹션 헤딩 제거, 후보 측정과 점수화가 구체화되었고 결과가 후보 객체로 전달된다.
하향 후보 생성
src/core/fig-extract.js
캡션 아래 이미지·잉크 시드와 유의미한 공백을 계산하고, 블록 단위 하향 스캔 및 bbox·유효성 검증을 통해 후보를 생성한다.
후보 선택 및 결과 반영
src/core/fig-extract.js
legacy 폴백을 유지하면서 suspicious 신호에 따라 하향 후보를 만들고, 정책 기반으로 상향·하향 후보 중 하나만 figs에 추가한다.

Estimated code review effort: 4 (Complex) | ~45 minutes

Sequence Diagram(s)

sequenceDiagram
  participant detectPage
  participant scan
  participant scanDown
  participant chooseCandidate
  detectPage->>scan: 상향 후보 측정
  detectPage->>scanDown: 하향 후보 생성
  scanDown-->>detectPage: 후보와 점수 반환
  detectPage->>chooseCandidate: 후보 선택 요청
  chooseCandidate-->>detectPage: 선택된 figure 반환
Loading

Possibly related PRs

  • enu3379/PDFViewer#2: fig-extract 엔진 통합과 초기 캡션 처리 흐름을 도입한 PR입니다.
  • enu3379/PDFViewer#22: 동일한 엔진 파일의 버전 및 figure 추출 파이프라인을 변경한 후속 관련 PR입니다.
  • enu3379/PDFViewer#24: matchCaption과 보충 캡션 변형을 함께 확장한 관련 PR입니다.

Suggested reviewers: enu3379

Poem

당근 든 토끼가 캡션을 찾네
위아래 후보를 재빠르게 살피네
Figure도, Supplement도 놓치지 않고
점수표 따라 하나를 고르네
깡충! v2.7.0 완성이다 🐇

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed 제목이 fig-extract를 v2.7.0으로 올리는 मुख्य 변경을 정확하고 간결하게 요약합니다.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch chore/bum-fig-extract-v2.7.0

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@src/core/fig-extract.js`:
- Around line 384-389: Update the BODY-stop check around hasImage(b0, b1) so
image detection only considers images overlapping the currently scanned column,
not merely matching the vertical range. Apply the same current-column constraint
to the raster bonus logic around the other hasImage usage (the additional
location noted in the review), preserving valid images in the active column
while excluding adjacent-column images.
- Around line 125-148: Update isCaption and the SPECIAL_CAP_RE/SPECIAL_CAP_RE2
matching path so separator-free supplementary captions such as “Supplementary
Figure 1” and “Extended Data Fig. 1” are not rejected by the length checks.
Preserve length filtering for other separator-free caption matches, while
allowing complete SPECIAL_CAP_RE* matches to return their match number.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 0fec66b0-ea95-4837-b1b7-4796ae8a33af

📥 Commits

Reviewing files that changed from the base of the PR and between bb335ea and d2a35c0.

📒 Files selected for processing (2)
  • docs/fig-extract-integration.md
  • src/core/fig-extract.js

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Caution

Inline review comments failed to post. This is likely due to GitHub's internal server error or limits when posting large numbers of comments. If you are seeing this consistently it is likely a permissions issue. Please check "Moderation" -> "Code review limits" under your organization settings.

Actionable comments posted: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@src/core/fig-extract.js`:
- Around line 384-389: Update the BODY-stop check around hasImage(b0, b1) so
image detection only considers images overlapping the currently scanned column,
not merely matching the vertical range. Apply the same current-column constraint
to the raster bonus logic around the other hasImage usage (the additional
location noted in the review), preserving valid images in the active column
while excluding adjacent-column images.
- Around line 125-148: Update isCaption and the SPECIAL_CAP_RE/SPECIAL_CAP_RE2
matching path so separator-free supplementary captions such as “Supplementary
Figure 1” and “Extended Data Fig. 1” are not rejected by the length checks.
Preserve length filtering for other separator-free caption matches, while
allowing complete SPECIAL_CAP_RE* matches to return their match number.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 0fec66b0-ea95-4837-b1b7-4796ae8a33af

📥 Commits

Reviewing files that changed from the base of the PR and between bb335ea and d2a35c0.

📒 Files selected for processing (2)
  • docs/fig-extract-integration.md
  • src/core/fig-extract.js
🛑 Comments failed to post (2)
src/core/fig-extract.js (2)

125-148: 🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

구분자 없는 보충 캡션을 길이 필터에서 탈락시키지 마세요.

SPECIAL_CAP_RE*는 줄 끝을 허용하지만, Line 144와 147의 제한은 Supplementary Figure 1이나 Extended Data Fig. 1 같은 완전 일치를 거부합니다. 캡션 본문이 다음 줄로 분리된 PDF에서 신규 캡션 형식을 놓치게 됩니다.

수정 예시
   if (m) {
     const prefix = m[1].toLowerCase().startsWith("extended") ? "ED" : "S";
-    return { num: `${prefix}.${m[2]}`, sep: m[3] || "" };
+    return { num: `${prefix}.${m[2]}`, sep: m[3] || "", allowBare: true };
   }
...
-    if (![".", ":", "|"].includes(match.sep) && stripped.length > 12) return null;
+    if (!match.allowBare && ![".", ":", "|"].includes(match.sep) && stripped.length > 12) return null;
...
-  if (![".", ":", "|"].includes(match.sep) && line.s.length > 14) return null;
+  if (!match.allowBare && ![".", ":", "|"].includes(match.sep) && line.s.length > 14) return null;
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

function matchCaption(s, compact) {
  let m = (compact ? SPECIAL_CAP_RE2 : SPECIAL_CAP_RE).exec(s);
  if (m) {
    const prefix = m[1].toLowerCase().startsWith("extended") ? "ED" : "S";
    return { num: `${prefix}.${m[2]}`, sep: m[3] || "", allowBare: true };
  }
  m = (compact ? LEADING_S_CAP_RE2 : LEADING_S_CAP_RE).exec(s);
  if (m) return { num: `S.${m[1]}`, sep: m[2] || "" };
  m = (compact ? CAP_RE2 : CAP_RE).exec(s);
  if (m) return { num: m[2].toUpperCase(), sep: m[3] || "" };
  return null;
}

function isCaption(line) {
  let match = matchCaption(line.s, false);
  if (!match) {
    const stripped = line.s.replace(/\s+/g, "");
    match = matchCaption(stripped, true);
    if (!match) return null;
    if (!match.allowBare && ![".", ":", "|"].includes(match.sep) && stripped.length > 12) return null;
    return match.num;
  }
  if (!match.allowBare && ![".", ":", "|"].includes(match.sep) && line.s.length > 14) return null;
  return match.num;
🧰 Tools
🪛 OpenGrep (1.25.0)

[ERROR] 126-126: Dynamic command passed to child_process.exec/execSync. Use child_process.execFile or spawn with an argument array instead.

(coderabbit.command-injection.exec-js)


[ERROR] 131-131: Dynamic command passed to child_process.exec/execSync. Use child_process.execFile or spawn with an argument array instead.

(coderabbit.command-injection.exec-js)


[ERROR] 133-133: Dynamic command passed to child_process.exec/execSync. Use child_process.execFile or spawn with an argument array instead.

(coderabbit.command-injection.exec-js)

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/core/fig-extract.js` around lines 125 - 148, Update isCaption and the
SPECIAL_CAP_RE/SPECIAL_CAP_RE2 matching path so separator-free supplementary
captions such as “Supplementary Figure 1” and “Extended Data Fig. 1” are not
rejected by the length checks. Preserve length filtering for other
separator-free caption matches, while allowing complete SPECIAL_CAP_RE* matches
to return their match number.

384-389: 🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

현재 스캔 열과 겹치는 이미지만 BODY 보호와 raster 가점에 사용하세요.

hasImage()가 세로 위치만 확인하므로, 인접 열의 이미지도 Line 386의 BODY 중단을 무효화하고 up 후보에 raster 가점을 줄 수 있습니다. 그 결과 본문을 포함한 잘못된 후보가 유효한 down 후보보다 우선될 수 있습니다.

수정 예시
-    const hasImage = (b0, b1) => pg.images.some(im => {
+    const hasImage = (b0, b1, bx0, bx1) => pg.images.some(im => {
       const it = im.top * S, ib = (im.top + im.h) * S;
-      return Math.min(ib, b1) - Math.max(it, b0) > 0.5 * (ib - it);
+      return Math.min(ib, b1) - Math.max(it, b0) > 0.5 * (ib - it) &&
+        ox(im, { left: bx0, w: bx1 - bx0 }) >
+          0.2 * Math.min(im.w, bx1 - bx0);
     });
...
-        if (nstop >= guard && !hasBorder(b0, b1) && !hasImage(b0, b1)) {
+        if (nstop >= guard && !hasBorder(b0, b1) &&
+            !hasImage(b0, b1, bx0, bx1)) {
...
-      const raster = incl.some(([a, b]) => hasImage(a, b));
+      const raster = incl.some(([a, b]) =>
+        hasImage(a, b, rx0 / S, rx1 / S));

Also applies to: 890-900

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/core/fig-extract.js` around lines 384 - 389, Update the BODY-stop check
around hasImage(b0, b1) so image detection only considers images overlapping the
currently scanned column, not merely matching the vertical range. Apply the same
current-column constraint to the raster bonus logic around the other hasImage
usage (the additional location noted in the review), preserving valid images in
the active column while excluding adjacent-column images.

@onetwothr1
onetwothr1 merged commit 774f7b0 into dev Jul 16, 2026
3 checks passed
@onetwothr1
onetwothr1 deleted the chore/bum-fig-extract-v2.7.0 branch July 16, 2026 23:52
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant